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

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


     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值