其实在平时开发、面试、技术交流都会提到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();            }        }    }}


更多相关文章

  1. [置顶] Android基于XMPP Smack Openfire开发IM(5)发送消息
  2. Android中桌面图标显示通知消息的数量
  3. Asynchronous HTTP Requests in Android(安卓)Using Volley
  4. Android学习笔记(38):Handler消息传递处理机制
  5. Android中的Handler:接受子线程发送的数据, 并用此数据配合主线
  6. Android:异步处理之Handler、Looper、MessageQueue之间的恩怨(三)
  7. Android(安卓)之 Choreographer 详细分析
  8. 【Android】实现登录、注册、数据库操作(极复杂)
  9. android中的ANR

随机推荐

  1. 多线程学习(三)那些队列可用于线程池
  2. 用翻译赚钱,翻译社规则调整
  3. Fedora写给Python的情书
  4. 值得关注的5个Python开源项目
  5. 2分钟理清计算机、Python和Pip的三角关系
  6. 用Python制作3D动画
  7. 如果你也用Win10,真的请备份!
  8. 不看教程,可能更浪费你的时间
  9. 在python中执行shell命令的6种方法
  10. 临摹源码 | 一比一手写Dubbo源码中的SPI(