码迷,mamicode.com
首页 > 其他好文 > 详细

Handler,Looper,Message,MessageQueue之间关系浅析

时间:2015-06-16 09:18:15      阅读:115      评论:0      收藏:0      [点我收藏+]

标签:

一、先看一下使用流程

1.在子线程中使用Handler实例

    /***********子线程使用Handler实例*********/
    private class LooperThread extends Thread
    {
        public Handler handler;
        @Override
        public void run()
        {
            Looper.prepare();
            handler = new Handler()
            {
                @Override
                public void handleMessage(Message msg)
                {        
                }
            };
            Looper.loop();
        }
    }

2、主线程(UI线程)中使用的Handler,Looper等
其实现在android/app/AcitvityThread.java文件中,如下:

public static void main(String[] args) {
        //前面一系列配置暂时不用关心
        SamplingProfilerIntegration.start();
        CloseGuard.setEnabled(false);
        Environment.initForCurrentUser();
        EventLogger.setReporter(new EventLoggingReporter());
        Security.addProvider(new AndroidKeyStoreProvider());
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);
        Process.setArgV0("<pre-initialized>");
        /************从这里开始,使用Looper*******************/
        Looper.prepareMainLooper();//对比:子线程中使用Looper.prepare();
 
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
 
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();//对比:子线程中自创建new Handler()
        }
 
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
 
        Looper.loop();//对比:这里两者相同
 
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

二、查看源码:
(一)prepare()
1、看一下Looper.prepare()的源码:
    /** 将当前线程初始化为一个Looper.所以你可以在start loop前先创建Handlers,再引用这个looper;
      * 要确保在调用本方法后调用#loop()方法;结束本方法使用#quit();
      */
    public static void prepare() {
        prepare(true);         //对比:下面将会看到主线程中的prepareMainLooper中将会使用prepare(false)
    }
 
    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));
    }
附I)这里引出了一个sThreadLocal,首先看其定义:

    // sThreadLocal.get() will return null unless you've called prepare().
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

    ThreadLocal类是个特殊的全局变量,其全局性只体现在自己的所在的线程(类名也体现出该特性),故因此每个线程的Looper都是独立的;
    ThreadLocal类Java本身已经给予实现,Android对其进行了实现优化;其主要思想仍为:ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单,在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本,Map中元素的键为线程对象,而值对应线程的变量副本
    前面源码中涉及到的get(),set(0方法分别为获取和设置当前线程所对应的线程局部变量值。

2、对比看一下prepareMainLooper():
   /**
     * Initialize the current thread as a looper, marking it as an
     * application's main looper. The main looper for your application
     * is created by the Android environment, so you should never need
     * to call this function yourself.  See also: {@link #prepare()}
     */
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                thrownew IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }
   
    /**
     * 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();
    }
附II): sMainLooper的定义:

    private static Looper sMainLooper;

和前面大致相同,只是定义了一个sMainLooper,get sThreadLocal获得一个Looper,让sMainLooper指向它;

(二)Handler

1、Handler部分源码:

Handler众多构造函数:

    public Handler() {
        this(null, false);
    }

    public Handler(Callback callback) {
        this(callback, false);
    }
 
    public Handler(Looper looper) {
        this(looper, null, false);
    }
 
    public Handler(Looper looper, Callback callback) {
        this(looper, callback, false);
    }
 
    public Handler(boolean async) {
        this(null, async);
    }
 
    public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

   /****************重点看此构造函数*********************/
    public Handler(Callback callback, boolean async) {
        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());
            }
        }
     /***************前面忽略,从这里开始看******************/
        mLooper = Looper.myLooper();//依然通过sThreadLocal获取到当前Thread的Looper实例,可见这里两者联系到一起
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;   //这里MessageQueue是Looper与Handler沟通的桥梁
        mCallback = callback;
        mAsynchronous = async;
    }
附I)mQueue的定义:final MessageQueue mQueue;

可见通过MessageQueue,Handler与Looper联系到一起;

(三)Looper.loop()处理事件流程

    public static void loop() {
        final Looper me = myLooper();//依然通过sThreadLocal获取到当前Thread的Looper实例
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;//获取到上面提到过的MessageQueue mQueue

        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();
        /****************循环处理消息*******************/
        for (;;) {
            Message msg = queue.next(); // 从MessageQueue中取出next消息
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                //表明当前MessageQueue正在退出
                return;
            }
 
            // 调试信息,跳过
            Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }
            /** 开始分派消息*/
            msg.target.dispatchMessage(msg);//Message中的定义Handler target,故dispatchMessage
                                            //最终调用Handler中的处理函数;
 
            /** 调试信息,跳过*/
            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }
 
            msg.recycleUnchecked();//回收处理完的消息Message
        }
    }
    由上loop()方法可以简单得出结论,Looper用以处理MessageQueue中的取出的Message,由MessageQueue是Handler及Looper所共用的,取出的Message则交由Handler进行处理。而Handler也能够通过post或者send等方式将Message添加到MessageQueue中供Looper后续进行取出处理。sThreadLocal保证了Looper是线程私有的,所有信息发送与处理都是在本线程中。

    prepare()用以在sThreadLocal中创建线程与该线程对应的Looper的键值对;new Handler或者getHandler创建的Handler都根据sThreadLocal.get()进行获取;创建的Handler与Looper共用MessageQueue;loop开始循环处理Messagequeue中的事件。其即为整个流程。

Handler,Looper,Message,MessageQueue之间关系浅析

标签:

原文地址:http://blog.csdn.net/woliuyunyicai/article/details/46513821

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!