Reputation: 1466
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!
Upvotes: 2
Views: 2188
Reputation: 4573
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.
Upvotes: 1
Reputation: 228
Handler is UI-threaded component. Usage of simple listener may cause CalledFromWrongThreadException
if you want to touch some UI.
AsyncTask although have onPreExecute
, onPostExecute
and onProgressUpdate
, which are just methods, which are running on UI thread. doInBackground
runs on separate thread
Upvotes: 0