android

Android: simple sync manager using Observer Pattern

I have a new blog post with an updated example an explanation about Android and RESTful web services. You should take a look here:

For my current project I have to create a sort of synchronization mechanism to upload some data to a web service (I’ve covered web services before on the blog). I’m going to complete that article by showing how to create a very simple synchronization manager that will let you communicate to your web service and the upper layers of your application using the Observer pattern.

It’s important to mention this is not a fully featured sync mechanisms because I will only show you how to do the upload process. Nevertheless with the bases presented on this article you will be able to easily implement these.

As I mention on the title, I’ll be using the Observer Pattern because of two reasons:

  1. I really don’t like the use of handlers in Java
  2. The Observer pattern is incredible easy to implement on the Android platform

Scenario

Let’s say we have an application that lets you create notes. When you open the application you have a dashboard with different options like “Create new note”, “App settings”, “See my notes” and so. Once you are done creating a note, you go back to your dashboard where you can choose to see the notes you have created by going to the “See my notes” Activity. From there, there will be an icon that indicates if the note has been uploaded or not (because you may not have an internet connection all the time).

Problem

The problem we are trying to solve is not uploading the note: we are trying to do the process more elegant and to inform the activities in real time of the result of the syncing process. To do so, we will be using a few patterns: As the title says, we will use the Observer pattern which will allow us to forget about using Handlers to communicate between the manager and the activities. The other pattern we will be using is the Singleton pattern to avoid having multiple instances of the Manager.

Solution

If you are familiar with the Observer pattern, you know the Observable objects will send information to the observers. This information is usually in form of messages. We will create a Message class that will hold the information we believe is important.

public final class SyncUpdateMessage {
    
    // message codes
    public static final int NO_CONNECTION = 1;
    public static final int SYNC_SUCCESSFUL = 2;
    public static final int SYNC_STARTED = 3;
    public static final int SYNC_CUSTOM_ERROR = 4;
    
    private int messageCode;
    private Object what;
    
    public SyncUpdateMessage(int messageCode, Object what){
        this.messageCode = messageCode;
        this.what = what;
    }
    
    public int getMessageCode(){
        return this.messageCode;
    }
    
    public Object getWhat(){
        return this.what;
    }
}

Now lets create the SyncManager class

public class SyncManager extends Observable{
    
    private static SyncManager instance = new SyncManager();

    public static SyncManager getInstance() {
        return instance;
    }
    private SyncManager() {
    }
    
    private boolean syncInProgress = false;
    
    public void sync(final String param1, final String param2, final int param3){
        
        if (syncInProgress)
            return;
        
        // example of a custom error message
        if (param2.equals("")) {
            setChanged();
            notifyObservers(new SyncUpdateMessage(SyncUpdateMessage.SYNC_CUSTOM_ERROR,
                    null));
            return;
        }
        
        // set flag
        syncInProgress = true;
        notifyObservers(new SyncUpdateMessage(SyncUpdateMessage.SYNC_STARTED,
                null));
        
        // all good, begin process
        new Thread(new Runnable() {

            @Override
            public void run() {
                
                Note note = databaseManager.getNote(String param1);
                String result = NoteUploader.uploadNote(note);

                setChanged();
                notifyObservers(new SyncUpdateMessage(
                        SyncUpdateMessage.SYNC_SUCCESSFUL, result));

                // release flag
                syncInProgress = false;
            }
        }).start();
    }
    
}

I’m not doing the upload methods because It exceeds the scope of the article. What’s important here is you to see how the manager tells the Observers what’s going on. You have to pay attention to the setChanged() and notifyObservers() methods.

There is a syncInProcess boolean that will prevent the cycle to enter again if we are already on it. Also I added a custom error.

Lets see how to use this on the Activities !

public class MainActivity extends Activity implements Observer {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // add observer
        SyncManager.getInstance().addObserver(this);
    }
    
    @Override
    protected void onDestroy() {
        SyncManager.getInstance().deleteObserver(this);
        super.onDestroy();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    private final Handler uiHandler = new Handler() {
    };

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

            SyncUpdateMessage msg = (SyncUpdateMessage) data;

            if (msg.getMessageCode() != SyncUpdateMessage.SYNC_SUCCESSFUL)
                return;

            Runnable visuals = new Runnable() {

                @Override
                public void run() {
                    uiHandler.post(new Runnable() {

                        @Override
                        public void run() {
                            // make changes on the UI here
                            refreshListViewItems();
                        }
                    });
                }
            };
            new Thread(visuals).start();
        }
    }
}

The code is really simple:

  • onCreate we register this Activity as an observer
  • onDestroy we do the inverse process to avoid having floating references all over the application
  • the update() method is where the magic happens

When the Observables call the setChanged() and then notifyObservers(), the registered Observers will trigger the update() method. To make changes on the UI we have to use a Handler, bur in this case is contained within the Activity and not used as a parameter.

Wrapping it up

As you see, this is a very simple sync manager. There are several ways to improve it but I wanted to show the basics. I’d like to add this code can be easily migrated to other languages (like c# for example) because what’s important here is the concept.

Hope it helps !

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s