回调是一种双向调用模式,就是说,被调用方在被调用时也会调用对方,这就叫回调。“If you call me, i will call you back”。
下面先看一个例子:
public class Text { public static void main(String[] args) { // TODO Auto-generated method stub A a = new A(); a.sendMessage(); } } interface callBack{ public void handMessage(String msg);//注册回调方法 } class A implements callBack{ private B b; public A(){ b = new B(); } @Override public void handMessage(String msg) { //回调方法 // TODO Auto-generated method stub System.out.println("success,"); } public void sendMessage(){ b.getMessage("I call you",this); } } class B { public void getMessage(String msg,callBack callBack) { // TODO Auto-generated method stub System.out.println("get your message,and i will call you back"); callBack.handMessage(msg); } }核心都在这里,A调用B后,把自己的引用传递给B,然后在B中再调用A,这就是回调。
getMessage("I call you",this);
接下来我们分析一下Handler中基于回调的消息处理机制。
先来回顾一下Handler的基本使用方式:
创建Handler对象,重写handleMessage方法处理接收到的消息:
Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); Log.v("TAG", "handleMessage-----------------------"); } };
创建一个子线程,用于发送Message消息:
class MyRunnable implements Runnable{ private Handler handler; public MyRunnable(Handler handler){ this.handler = handler; } @Override public void run() { // TODO Auto-generated method stub Message msg = handler.obtainMessage(); msg.arg1 = 1; Log.v("TAG", "MyThread--------- --------------"); msg.sendToTarget(); } }
MyRunnable run = new MyRunnable(handler); Thread mThread = new Thread(run); mThread.start();
Message msg = handler.obtainMessage();我们看看Handler的源代码:只粘贴了用到的一部分方法
public final Message obtainMessage(int what, int arg1, int arg2, Object obj) { return Message.obtain(this, what, arg1, arg2, obj); } public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); } public boolean sendMessageAtTime(Message msg, long uptimeMillis) { MessageQueue queue = mQueue; if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); return false; } return enqueueMessage(queue, msg, uptimeMillis); } private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); } public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
public static Message obtain(Handler h, int what, int arg1, int arg2, Object obj) { Message m = obtain(); m.target = h; m.what = what; m.arg1 = arg1; m.arg2 = arg2; m.obj = obj; return m; } public void sendToTarget() { target.sendMessage(this); }
msg.sendToTarget();看上面的Message类源码,通过刚才得到的Handler引用,又调用了Handler中的方法,这里就达到了回调的目的,主体是Message和Handler,其中涉及了一些类,比如:MessageQueue,Looper,这两个类的存在只是为了对消息的存储和抽取进行了一定的封装。至于回调后怎么执行了handleMessage()方法,看以上Handler的源码,发现消息最后是在放进了MessageQueue类中,这是一个消息队列,它通过Looper类把消息队列中的消息给抽取出来,代码如下
public static void loop() { final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process, // and keep track of what that identity token actually is. Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } // This must be in a local variable, in case a UI event sets the logger Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } msg.target.dispatchMessage(msg); if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } 。。。 }