Search code examples
javaandroidandroid-asynctaskobserver-patternandroid-handler

Listeners observer design pattern with Handler


I was dealing recently with a question I'm not sure how to answer. I wrote a code example for some AsyncTask that I want to perform. I read somewhere on the net that someone has implemented the AsyncTask and the Handler as inner classes and I wanted to scale that a little bit and make less coupling so I made separated class for those so I can reuse them with more than one Activity. Because I had to do some different UI things on each Activity I decided to make those activities implement an interface so I can react to each event with same methods.

What I don't understand is why do I need the handler object that will handle the messaging for event occurrence? can't I just use the listeners observer pattern? and then the question that I asked my self and can't understand the answers around the web is what is the difference between my listener observer implementation and the handler object we get from Android.

Here is my code example:

Activity 1:

public class SomeActivity extends Activity implements MyListener{

    MyAsyncTask myTask;
    MyHandler handler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        handler = new MyHandler();
        myTask = new MyAsyncTask(handler);
        // initilize the activity views etc...
    }

    @Override
    public void do1(){
        // DO UI THINGS FOR ACTIVITY 1 IN A CALLBACK TO DO1 EVENT
    }

    @Override
    public void do2(){
        // DO UI THINGS FOR ACTIVITY 1 IN A CALLBACK TO DO2 EVENT
    }
}

Activity 2:

public class OtherActivity extends Activity implements MyListener{

    MyAsyncTask myTask;
    MyHandler handler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        handler = new MyHandler();
        myTask = new MyAsyncTask(handler);
        // initilize the activity views etc...
    }

    @Override
    public void do1(){
        // DO UI THINGS FOR ACTIVITY 2 IN A CALLBACK TO DO1 EVENT
    }

    @Override
    public void do2(){
        // DO UI THINGS FOR ACTIVITY 2 IN A CALLBACK TO DO2 EVENT
    }
}

Listener interface:

public interface MyListener{
    void do1();
    void do2();
}

AsyncTask implementation:

public class MyAsyncTask extends AsyncTask<Void,Void,String>{
    private MyModel m;

    public MyAsyncTask(Handler h){
        m = new MyModel();
        m.setHandler(h);
    }

    protected String doInBackground(Void... params) {
        // do something in background with MyModel m
        return null;            
    }
}

Handler implementation:

public class MyHandler extends Handler {

    Vector<MyListener> listeners = new Vector<>();

    @Override
    public void handleMessage(Message msg) {
        switch(msg.what){
            case 1:
                // do something for case 1
                fireMethod1();
                break;
            case 2:
                // do something for case 2
                fireMethod2();
                break;
        } 
    }

    public void registerListener(MyListener l){
        listeners.add(l);
    }

    public void unregisterListener(MyListener l){
        listeners.remove(l);
    }

    private void fireMethod1(){
        for(MyListener l : listeners){
            l.do1();
        }
    }

    private void fireMethod2(){
        for(MyListener l : listeners){
            l.do2();
        }
    }

}

Some demo model I created:

public class MyModel{

    private Handel h;

    public MyModel(){
        // at some point send message 1 or message 2 ...
    }

    public void setHandler(Handler h){
        this.h = h;
    }

    private void sendMessage1(){
        h.obtainMessage(1, null);
    }

    private void sendMessage2(){
        h.obtainMessage(2, null);
    }
}

if it is too hard to read the code let me know, and if you don't want to read the code please help me to answer what is the difference between Handler and listening to events with the observer pattern? are they pretty much different solutions for same problem? thanks!


Solution

  • what is the difference between Handler and listening to events with the observer pattern?

    The difference is that when you use a listener you call a method synchronously on the same thread. When you use a Handler you synchronously add a message to the MessageQueue but it is handled only after those messages that are already in the queue.

    For example, if you are using a UI handler and you already called finish() on the activity and then added your message, it will be inserted after onStop() and onDestroy(). You can't achieve this with a listener.

    The advantage of handlers is that you just add messages to queues and you don't care about threading. You can easily add a message to the UI handler from the background thread. If you use a listener from the background thread, it will be called on a background thread synchronously.

    are they pretty much different solutions for same problem?

    No, they are not. Handlers help you to decouple android components which is critical for Android, I think. If you use listeners you will be relying on strong references only which in some cases is not possible because you might leak a memory.