回调是一种双向调用模式,就是说,被调用方在被调用时也会调用对方,这就叫回调。“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();
}
}
启动子线程,发送Message消息:
MyRunnable run = new MyRunnable(handler);
Thread mThread = new Thread(run);
mThread.start();
先来看看 子线程怎么得到Message对象的:
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);
}
}
它调用了Message类的静态方法obtain(),并传递了一个this,Message源代码如下:
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);
}
其中的target就是Message类中定义的一个Handler引用,这样Handler的引用就传到了Message中。接着在子线程中我们执行发送消息的方法:
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);
}
。。。
}
以上的msg.target是一个Hanlder对象,调用dispatchMessage()方法后,回来看Handler源码,发现在这里调用了handleMessage()方法。到这里,Handler的整个消息回调处理流程就结束了。至于它是怎么使用MessageQueue,Looper对消息进行处理的,接下来再写。