您的位置:首页 > 产品设计 > UI/UE

Handler+Message+MessageQuque+Looper 异步加载类 消息处理机制 分析

2013-11-28 18:18 274 查看
其实在平时开发、面试、技术交流都会提到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 timeSamplingProfilerIntegration.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(newLogPrinter(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()");}//初始化MessageQueuemQueue = 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();}}}}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐