Coder QA: Observing Changes

Using the observer pattern to display changes in network state on Android & Java

Question: I’m developing an Android program in Java, and I have a BroadcastReceiver instantiated by an Activity. The BroadcastReceiver receives and processes an intent, and I would like the Activity to determine if it should do something with that result. How can I make that happen?

Questions like this one come up all of the time, and as programmers march towards seniority, or senility as the case may be, they begin to recognize these types of questions as indicators of the need for a design pattern. While it’s true that there are probably quite a few ways to solve this particular problem ranging from simple to enormously complex but adaptable, today I will focus on a single design pattern I’ve used to solve this problem – the Observer Pattern.

Reusable solutions to common problems for developers

When I talk to developers about design patterns, I always reference the Gang of Four. The definition for the Observer Pattern according to their website is:

“Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.”

The Gang of Four – Observer

The definition describes two types of objects. The first object has a state or something else that can change or be updated. This object is called the subject. The other object(s) involved area dependent on the subject, and need to know when that change or update occurs. These objects are observing the subject, and thus bear the namesake of the pattern, Observers.

For those reading this that may not be familiar with Android, I’ll just cover some some basics. An intent is an object that describe an action to be performed and it’s result. Intents are used throughout android as a basic messaging system. A broadcast receiver is a special type of class from which you can inherit on which a method will fire when an intent is broadcast from anywhere in the system, provided it meets filter criteria that you specify in your inherited version. An activity is a basic component of the UI system which describes a view or set of views and the actions taken around that view. Depending on your design, you can see a task as a kind of controller or, in some cases, a task.

Adding some practicality to the mix

So now, let’s make our situation a little more real. We are building an app for Android that has a single activity called WiFiMonitorActivity which displays a message when the WiFi state changes. We’ve learned that in android will broadcast an intent with the name android.net.wifi.WIFI_STATE_CHANGED and that we need to create a BroadcastReceiver to catch this intent. Assuming we have all of this already in place, we come across a problem (see this tutorial for setting up a broadcast receiver). We would like our activity to set a label when the receiver receives the broadcast. The receiver knows nothing of the activity, and we don’t want to make a hard dependency if we can avoid doing so.

Next we need to give some thought to what specific objects in our code will represent our more abstract definitions in the observer pattern. The object that will notify other objects of a change or update is the subject. In our case the subject is the BroadcastReceiver class since the receiver will be responsible for telling other objects that an intent has been received. The other object in this mix is the Observer. In this case, we only one observer. Our observer is the Activity class because the activity needs to be notified when the broadcast receiver has received an intent. Since we want to loosely couple together the observer to the subject, we cannot use the activity class directly. Instead, we need to abstract the observer and allow the activity to implement the observer functionality. The best way to do that is to use an interface.

Implementing a solution in Java

We are ready to implement our Observer pattern. We will begin by creating an interface, which will describe our Observer. Create a new interface called BroadcastReceiverObserver. To the interface, add a single void method prototype called BroadcastReceived with no parameters. Your interface will look like this:

public interface BroadcastReceiverObserver {
public void BroadcastReceived();
}

Have your activity class implement the new interface. You will add the implements keyword, specify the BroadcastReceiverObserver type, and then make sure you have an implementation of the BroadcastReceived method. The activity class will look something like this:

public class MainActivity extends Activity implements BroadcastReceiverObserver {
private MyReceiver receiver;

public MainActivity() {
....
receiver = new MyReceiver();

registerReceiver(....
}

@Override
public void BroadcastReceived() {
Toast.makeText("Received Intent", Toast.LENGTH_LONG).show();
}

Next, add a property to the subject class, the Broadcast Receiver, of the type BroadcastReceiverObserver. Create a getter and a setter for the variable. Now go to your onReceive method in the receiver, and add some code to invoke the observer when a broadcast is received:

if (mObserver != null) {
mObserver.BroadcastReceived();
}

In your activity constructor, call the new setter you created on your receiver passing “this” as the parameter:

receiver.setObserver(this);
Testing your results

When you run this, you should see a small toast message every time the Wifi state changes. You can expand on this by changing your observer property on the subject from a single object to a collection of objects and then adding methods to add and remove multiple observers. You will then also need to loop through the list of observers in the onReceive method of the broadcast receiver.

In my experience, the practical application of design patterns comes much later than learning about them. I like to try to help developers shorten that gap, and at the same time, provide them with a set of tools that will help to solve problems of all varieties.

Posted in Articles, Software.

Leave a Reply

Your email address will not be published. Required fields are marked *

eleven + twelve =