我们先大概了解一下异步处理的流程:
1、首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
2、Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。
3、Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。
4、Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。
5、在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。
下面借用一张图片来直观的了解一下:
looper里面的for循环,不断的在消息队列中进行查找,若handle发送了消息即可调用handleMessage来进行处理
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mRun = true;
mThread = Thread.currentThread();
}
可以看出在looper的构造方法中创建了一个消息队列,然后在loop方法中:
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);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycle();
}
}
拿到消息队列
queue 之后就进入了无限循环,用next取出一条消息。没有则阻塞,有则调用msg.target.dispatchMessage(msg) (msa.target其实就是handler对象),之后进入到handler对象里面:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
可以看到dispatchmessage这里直接调用了handlemessage方法
/**
* Subclasses must implement this to receive messages.
*/
public void handleMessage(Message msg) {
}
这里是空?回顾下我们我们一般new handle的时候复写的这个方法:
public class HandlerTestActivity extends Activity {
private TextView tv;
private static final int UPDATE = 0;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO 接收消息并且去更新UI线程上的控件内容
if (msg.what == UPDATE) {
// Bundle b = msg.getData();
// tv.setText(b.getString("num"));
tv.setText(String.valueOf(msg.obj));
}
super.handleMessage(msg);
}
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv = (TextView) findViewById(R.id.tv);
new Thread() {
@Override
public void run() {
// TODO 子线程中通过handler发送消息给handler接收,由handler去更新TextView的值
try {
for (int i = 0; i < 100; i++) {
Thread.sleep(500);
Message msg = new Message();
msg.what = UPDATE;
// Bundle b = new Bundle();
// b.putString("num", "更新后的值:" + i);
// msg.setData(b);
msg.obj = "更新后的值:" + i;
handler.sendMessage(msg);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
}
就是我们需要实现的代码,因此这里一个完整的异步消息处理就完成了