Handler原理
Handler用于Android异步消息处理,在Android中子线程不允许进行UI操作,解决办法是在子线程中创建一个Message对象,让后借助Handler发送给UI线程,再由UI线程中的Hnadler调用handleMessage()方法获取Message对象并进行处理,从而实现更新UI。
主线程创建时系统默认调用了Looper.prepare(),所以子线程中若想创建Handler首先需要调用Looper.prepare()。
一个Looper对应一个MessageQueue,MessageQueue中提供入队enqueueMessage()和出队的相关方法,入队将所有消息按时间来进行排序,出队是在Looper.loop()中通过一个死循环不断调用MessageQueue的next()方法取出消息,如果消息队列中没有消息则会进入阻塞状态。loop()方法中会将消息传递到Handler的dispatchMessage()方法中,在这个方法中会调用Handler的handleMessage()处理消息。
一个标准的异步消息处理线程的写法
class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } }
另外除了发送消息之外,我们还有以下几种方法可以在子线程中进行UI操作:
1. Handler的post()方法
2. View的post()方法
3. Activity的runOnUiThread()方法
Handler的post:调用了sendMessageDelayed()方法去发送一条消息,使用了getPostMessage()方法将Runnable对象转换成了一条消息。
handler = new Handler(); new Thread(new Runnable() { @Override public void run() { handler.post(new Runnable() { @Override public void run() { // 在这里进行UI操作 } }); } }).start();
View的post:调用了Handler的post()
Activity中的runOnUiThread():如果当前线程不是UI线程,则调用Handler的post(),否则直接调用Runnable的run()
总结:
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)最终调用的方法。
参考文献:http://blog.csdn.net/guolin_blog/article/details/9991569
http://blog.csdn.net/lmj623565791/article/details/38377229