Android Observers and Observables – How to Update Activities Automatically Upon Data Changes!

Extending the Android Observer and Observable Classes for Auto Updates

The beauty of using an object oriented language such as Java is the ability to extend other classes on your object. Two awesome example of this are the Java Observer and Observable classes. By extending the Observable class on your data object (model), you are able to assign Observers which listen for changes in said data model. When the data changes, the Observer is notified automatically and fires its update() method.

Refresh your Views in the update() Method

The update() method is an obvious place to put your code which refreshes the views impacted by the changes in data, this is where the linkage between the views and the data model occurs (usually in the Android Activity). The beauty of using the Observer and Observable classes is that the data model, views and controller (the Activity that updates the views) are all separated. That is, you can use the data model for whatever you want, if you change the views it won’t break the data model and vice versa. This makes your app much simpler to understand and easier to update later down the road.

How this Example Works

Below I’ve created a very simple, but hopefully effective example which demonstrates using Observers and Observables to automatically update views upon changes in data. The Activity ObserverExample is registered as on Observer on the data model Score and acts as the controller in our application. When the Score changes, ObserverExample is notified and the method update() fires, within that method the app fires another method setScore() which refreshes the score to the new values.

Note this method of “wiring” up an app is called the Model-View-Controller paradigm. As you can see from the code, it simplifies the app by ensuring no parts of the app are tightly coupled to the other, this is important for creating simplistic and extensible code.

Take a look at the code below, also be sure to grab the .ZIP of the Eclipse Project and try it for yourself!

The main Activity ObserverExample.java

package com.ootpapps.observerexample;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import java.util.Observable;
import java.util.Observer;

public class ObserverExample extends Activity implements Observer {

    // Button variables for our 4 UI buttons which perform touchdowns and field
    // goals for the Home and Away teams.
    Button button1;
    Button button2;
    Button button3;
    Button button4;

    // Score variable for the Score object we'll be using to track and report
    // out both teams' scores.
    Score score;

    // TextView variables for our scoreboard display, #2 is Home score, #4 is
    // Vistors score.
    TextView textView2;
    TextView textView4;

    // Set some constants to make the code more human-readable.
    private static final int HOME = 1;
    private static final int VISITOR = 2;

    @Override
    public void update(Observable observable, Object data) {

        // Set the score to the current score each time there's a change.
        // Creating a helper method is a nice way to simplify the code here.
        setScore();
    }

    // Grabs the score for the Home team and Away team and displays them in
    // the correct TextView's of the scoreboard.

    private void setScore() {

        textView2.setText(String.valueOf(score.getScore(HOME)));
        textView4.setText(String.valueOf(score.getScore(VISITOR)));
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Create a new score object, this will contain all of the logic to
        // track and report out both team's scores.
        score = new Score();

        // Score is an Observable class, therefore, we can use the method
        // addObserver to add this Activity as an Observer using it's local
        // context. This is the magic sauce that enables instant updates
        // whenever the Score changes. When the Score reports a change, the
        // update() method runs in this Activity.
        score.addObserver(this);

        // This code ties in our TextView variables to the actual ID's of the UI
        // elements themselves.
        textView2 = (TextView) findViewById(R.id.textView2);
        textView4 = (TextView) findViewById(R.id.textView4);

        // Ties in the ID of the button to our variable set above.
        button1 = (Button) findViewById(R.id.button1);

        // Creates a new instance of OnClickListener which fires the onClick()
        // method upon, well, a click.
        button1.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                // Update the score by running the touchDown() method for the
                // Home team.
                score.touchDown(HOME);

            }
        });

        // Same idea as above repeated for buttons 2 - 4.
        button2 = (Button) findViewById(R.id.button2);

        button2.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                // Update the score by running the fieldGoal() method for the
                // Home team.
                score.fieldGoal(HOME);

            }
        });

        button3 = (Button) findViewById(R.id.button3);

        button3.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                score.touchDown(VISITOR);
            }
        });

        button4 = (Button) findViewById(R.id.button4);

        button4.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                score.fieldGoal(VISITOR);
            }
        });

    }

}

The data model Score.java

package com.ootpapps.observerexample;

import java.util.Observable;

// In order to report changes to any interested objects, such as Activities, we
// need to extend the Observable class. This enables other objects to register
// themselves as an Observer by using the addObserver() method.
public class Score extends Observable {

    // Initialize the score, scores always start at zero.
    private int home_score = 0;
    private int visitor_score = 0;

    public Score() {

    }

    // Grant 1 point to the team based on the variable fed in HOME == 1
    // and VISITOR == 2;
    public void fieldGoal(int team)
    {

        switch (team) {
            case 1:
                this.home_score = this.home_score + 1;
                break;

            case 2:
                this.visitor_score = this.visitor_score + 1;
                break;
        }

        triggerObservers();

    }

    // Returns the score of the Home or Visitor teams depending on which
    // variable is fed.
    public int getScore(int team) {

        switch (team) {
            case 1:
                return home_score;
            case 2:
                return visitor_score;
        }

        return 0;
    }

    // Adds six points to score of the team fed in as a variable, HOME == 1 and
    // VISITOR == 2
    public void touchDown(int team) {

        switch (team) {
            case 1:
                this.home_score = this.home_score + 6;
                break;

            case 2:
                this.visitor_score = this.visitor_score + 6;
                break;
        }

        triggerObservers();
    }

    // Create a method to update the Observerable's flag to true for changes and
    // notify the observers to check for a change. These are also a part of the
    // secret sauce that makes Observers and Observables communicate
    // predictably.
    private void triggerObservers() {

        setChanged();
        notifyObservers();
    }

}

Layout XML file activity_main.xml



    

        

        

        

        
    

    

    

Download the .ZIP of the Eclipse Project here! Enjoy and please leave me feedback in the comments, I appreciate it!

Share your love
Default image
Ryan Park
Ryan is a self-taught Android developer who's passionate about designing powerful apps with simple & intuitive user interfaces. Ryan's currently maintaining his hit app Kids Zone as it continues to rapidly grow each day. When not fixing bugs and writing features you'll find Ryan out for a drive, working out or petting his chihuahuas!

3 Comments

  1. nice! thanks. Simple yet I was not used to this pattern. This will be very useful for my projects. I’ll try this =)

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.