其实在平时开发、面试、技术交流都会提到Android消息处理机制,记得有次去面试有问道,消息处理流程,我相信这个对于开发Android两年都很简单,但是具体问道每个类作用和具体回调机制,每个对象分布在那个线程里,这时候就有点不清楚了,我回来之后就详细研究了Handler、Message、MessageQueue、Looper,ActivityThread,总结如下:
一.对象描述
1.应用程序启动在attach方法中加载ActivityThread线程管理类,在main()中调用looper循环读取消息队列.
2.Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列),消息处理机制核心功能就在Looper里面处理,Looper通过next操作先从MessageQueue取消息,然后通过disptchMessage方法通知Handler回传给
3.Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里,或者接收Looper(从Message Queue取出)所送来的消息。
4.Message Queue(消息队列),用于管理消息队列,在Handler初始化的时候会创建一个Message Queue 对象和Looper对象。
二.应用启动一个Looper循环读取消息队列流程如下:
//在Activity中attach流程时,传入ActivityThread线程对象
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config)
//在ActivityThread main中启动设置looper对象,并启动循环操作
public static void main(String[] args) {
/// M: Retrieve the information from AMS @{
if ( args != null && args.length > 0 ) {
if ( args[0].equals("enable") ) {
mEnableAppLaunchLog = true;
}
if ( args[1].equals("true") ) {
mIsUserBuild = true;
}
if ( args[2].equals("true") ) {
mBooted = true;
}
}
/// @}
logAppLaunchTime(TAG, "ActivityThread is created"); /// M: It's for debugging App Launch time
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
if (sMainThreadHandler == null) {
sMainThreadHandler = new Handler();
}
ActivityThread thread = new ActivityThread();
thread.attach(false);
AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
/// M: ALPS00270724 message history mechanism @{
if (!"user".equals(android.os.Build.TYPE)) {
Looper.myLooper().setMessageLogging(new MessageLogger());
}
/// @}
//执行looper循环消息循环操作
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
三.讲向消息队列加入消息详细流程分析如下:
下面我们先从Handler讲起,Handler是异步加载类,先从Handler初始化函数分析。
import android.util.Log;
import android.util.Printer;
import java.lang.reflect.Modifier;
public class Handler {
/*
* Set this flag to true to detect anonymous, local or member classes
* that extend this Handler class and that are not static. These kind
* of classes can potentially create leaks.
*/
private static final boolean FIND_POTENTIAL_LEAKS = false;
private static final String TAG = "Handler";
final MessageQueue mQueue;
final Looper mLooper;
final Callback mCallback;
IMessenger mMessenger;
/**
* Callback interface you can use when instantiating a Handler to avoid
* having to implement your own subclass of Handler.
*/
public interface Callback {
public boolean handleMessage(Message msg);
}
/**
* Subclasses must implement this to receive messages.
*/
public void 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);
}
}
/**
*
*初始化Handler对象
*
*/
public Handler() {
//Java反射机制来验证是不是Handler对象
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
//获取本线程的looper对象,Looper.myLooper就是返回一个同步线程类
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
//初始化MessageQueue
mQueue = mLooper.mQueue;
mCallback = null;
}
/**
* Constructor associates this handler with the queue for the
* current thread and takes a callback interface in which you can handle
* messages.
*/
public Handler(Callback callback) {
}
/**
* 由外部设置looper
*
*/
public Handler(Looper looper) {
}
/**
* 由外部设置looper,和回调对象。
*
*/
public Handler(Looper looper, Callback callback) {
}
/**
*
* sendMessageAtTime是最终加入消息队列的方法,在设置时间戳后加入消息对象中,以时间戳为队列
* uptimeMillis参数是时间戳,
* Message 是消息对象,
*
*
*/
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
//这个很关键,这个是指定消息回调对象,
msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);
}
else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}
/**
* Enqueue a message at the front of the message queue, to be processed on
* the next iteration of the message loop. You will receive it in
* {@link #handleMessage}, in the thread attached to this handler.
* <b>This method is only for use in very special circumstances -- it
* can easily starve the message queue, cause ordering problems, or have
* other unexpected side-effects.</b>
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean sendMessageAtFrontOfQueue(Message msg)
{
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
msg.target = this;
sent = queue.enqueueMessage(msg, 0);
}
else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}
/**
* 从一个消息队列中删除一个消息
*
*/
public final void removeMessages(int what) {
mQueue.removeMessages(this, what, null);
}
final IMessenger getIMessenger() {
synchronized (mQueue) {
if (mMessenger != null) {
return mMessenger;
}
mMessenger = new MessengerImpl();
return mMessenger;
}
}
private final class MessengerImpl extends IMessenger.Stub {
public void send(Message msg) {
Handler.this.sendMessage(msg);
}
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
private static Message getPostMessage(Runnable r, Object token) {
Message m = Message.obtain();
m.obj = token;
m.callback = r;
return m;
}
private static void handleCallback(Message message) {
message.callback.run();
}
}
四.讲Looper线程队列管理流程详解:
//Looper类分析
public class Looper {
//static变量,判断是否打印调试信息。
private static final boolean DEBUG = false;
private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
// sThreadLocal.get() will return null unless you've called prepare().
//线程本地存储功能的封装,TLS,thread local storage,什么意思呢?因为存储要么在栈上,例如函数内定义的内部变量。要么在堆上,例如new或者malloc出来的东西
//但是现在的系统比如Linux和windows都提供了线程本地存储空间,也就是这个存储空间是和线程相关的,一个线程内有一个内部存储空间,这样的话我把线程相关的东西就存储到
//这个线程的TLS中,就不用放在堆上而进行同步操作了。
private static final ThreadLocal sThreadLocal = new ThreadLocal();
//消息队列,MessageQueue,看名字就知道是个queue..
final MessageQueue mQueue;
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
//这个loop是在ActivityThread对象中main启动时调用loop方法
//这个是static函数喔!
public static final void loop() {
Looper me = myLooper();//从该线程中取出对应的looper对象
MessageQueue queue = me.mQueue;//取消息队列对象...
while (true) {
Message msg = queue.next(); // might block取消息队列中的一个待处理消息..
//if (!me.mRun) {//是否需要退出?mRun是个volatile变量,跨线程同步的,应该是有地方设置它。
// break;
//}
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
if (me.mLogging!= null) me.mLogging.println(
">>>>> Dispatching to " + msg.target + " "
+ msg.callback + ": " + msg.what
);
msg.target.dispatchMessage(msg);
if (me.mLogging!= null) me.mLogging.println(
"<<<<< Finished to " + msg.target + " "
+ msg.callback);
msg.recycle();
}
}
}
}