Android消息处理机制(源码分析)
前言
Looper类分析
package com.example.testlibrary; import android.os.Handler; import android.os.Looper; public class LooperTheread extends Thread{ public Handler mhHandler; @Override public void run() { // 1. 调用Looper Looper.prepare(); // ... 其他处理,例如实例化handler // 2. 进入消息循环 Looper.loop(); } }
通过1、2两步核心代码,你的线程就升级为Looper线程了。下面,我们对两个关键调用1、2进行逐一分析。
Looper.prepare()
// 每个线程中的Looper对象其实是一个ThreadLocal,即线程本地存储(TLS)对象 static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); public static void prepare() { prepare(true); } private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }
根据上面的源码可知,prepare会在调用线程的局部变量中设置一个Looper对象,并且一个Thread只能有一个Looper对象。这个调用线程就是LooperThread的run线程。来看一下Looper对象的构造源码:
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }通过源码,我们可以轻松了解Looper的工作方式,其核心就是将Looper对象定义为ThreadLocal。如果不理解ThreadLocal,可以参考我这篇文章:正确理解ThreadLocal
Looper循环
/** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the 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."); } // 取出这个Looper的消息队列 final MessageQueue queue = me.mQueue; for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } // 处理消息,Message对象中有一个target,它是Handler类型 msg.target.dispatchMessage(msg); msg.recycle(); } } /** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */ public static Looper myLooper() { return sThreadLocal.get(); }通过上面的分析会发现,Looper的作用是:
Handler分析
什么是handler?handler扮演了往MessageQueue里添加消息和处理消息的角色(只处理由自己发出的消息),即通过MessageQueue它要执行一个任务(sendMessage),并在loop到自己的时候执行该任务(handleMessage),整个过程是异步的。初识Handler
final MessageQueue mQueue; // Handler中也有一个消息队列 final Looper mLooper; // 也有一个Looper final Callback mCallback; // 有一个回调类这几个成员变量的使用,需要分析Handler的构造函数。Handler一共有四个构造函数,它们的区别就在于对上面成员变量的初始化上,下面我们来看一下四个构造函数的源码:
// 构造函数1 public Handler() { // 获得调用线程的Looper mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } // 得到Looper的消息队列 mQueue = mLooper.mQueue; // 无callback设置 mCallback = null; } // 构造函数2 public Handler(Callback callback) { // 获得调用线程的Looper mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } // 得到Looper的消息队列 mQueue = mLooper.mQueue; // 和构造函数1相比,多了callback设置 mCallback = callback; } // 构造函数3 public Handler(Looper looper) { // looper由外部传入,是哪个线程的Looper不确定 mLooper = looper; mQueue = mLooper.mQueue; mCallback = null; } // 构造函数4 public Handler(Looper looper, Callback callback) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; }通过上面的构造函数,我们可以发现,Handler中的MessageQueue最终都会指向关联Looper的MessageQueue。
Handler真面目
public class LooperThread extends Thread{ public Handler mhHandler; @Override public void run() { // 1. 调用Looper Looper.prepare(); // ... 其他处理,例如实例化handler Handler handler = new Handler(); // 2. 进入消息循环 Looper.loop(); } }加入Handler的效果图如下所示:
public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); // 得到空的message m.callback = r; // 将runnable设置为message的callback return m; } public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }最终发送消息都会调用sendMessageAtTime函数,我们看一下它的源码实现:
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; // 将Message的target设置为自己,然后加到消息队列中 if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
Handler处理消息
讲完了消息发送,再看一下Handler是如何处理消息的。消息的处理是通过核心方法dispatchMessage(Message msg)与钩子方法handleMessage(Message msg)完成的,源码如下:/** * Handle system messages here. */ public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } private static void handleCallback(Message message) { message.callback.run(); } /** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) { }dispatchMessage定义了一套消息处理的优先级机制,它们分别是:
Handler的用处
Message
/** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. */ public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; sPoolSize--; return m; } } return new Message(); } /** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}). */ public Message() { }
/** * arg1 and arg2 are lower-cost alternatives to using * {@link #setData(Bundle) setData()} if you only need to store a * few integer values. */ public int arg1; /** * arg1 and arg2 are lower-cost alternatives to using * {@link #setData(Bundle) setData()} if you only need to store a * few integer values. */ public int arg2; /** * Sets a Bundle of arbitrary data values. Use arg1 and arg1 members * as a lower cost way to send a few simple integer values, if you can. * @see #getData() * @see #peekData() */ public void setData(Bundle data) { this.data = data; }3. 用Message.what来标识信息,以便用不同方式处理message。
示例代码
public class MainActivity extends Activity { TextView mTextView; MyHandler mHandler = new MyHandler(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextView = (TextView)findViewById(R.id.test1); new Thread(new UpdateTitleTask(mHandler)).start(); } private class MyHandler extends Handler { @Override public void handleMessage(Message msg) { Bundle bundle = msg.getData(); mTextView.setText(bundle.getString("title", "")); } } }
public class UpdateTitleTask implements Runnable{ private Handler handler; public UpdateTitleTask(Handler handler) { this.handler = handler; } private Message prepareMsg() { Message msg = Message.obtain(); Bundle bundle = new Bundle(); bundle.putString("title", "From Update Task");; msg.setData(bundle); return msg; } @Override public void run() { try { Thread.sleep(2000); Message msg = prepareMsg(); handler.sendMessage(msg); } catch (InterruptedException e) { } } }
参考文献
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。