码迷,mamicode.com
首页 > 移动开发 > 详细

Android笔记(三十三) Android中线程之间的通信(五)Handle、Looper和MessageQueue

时间:2015-09-18 18:30:34      阅读:190      评论:0      收藏:0      [点我收藏+]

标签:

ThreadLocal

         往下看之前,需要了解一下Java的ThreadLocal类,可参考博文:

    解密ThreadLocal

Looper、Handler和MessageQueue

       我们分析一下之前的这段代码,查看一下Handler机制中,Handle、Looper和MessageQueue之间到底是什么关系

class WorkerThread extends Thread {
        @Override
        public void run() {
            super.run();
            Looper.prepare();
            handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    Log.d("TTTT", "handleMessage:" + Thread.currentThread().getName());
                    int i = msg.what;
                    Log.d("TTTT", "收到了消息对象:" + i);
                }
            };
            Looper.loop();
        }
    }

1. 首先执行 Looper.prepare() ;

       查看Looper的源代码,路径为:sources\android-19\android\os\Looper.java

       首先,Looper类的几个成员变量

    // sThreadLocal.get() will return null unless you‘ve called prepare().
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    private static Looper sMainLooper;  // guarded by Looper.class
    final MessageQueue mQueue;
    final Thread mThread;

       这就表明,每一个Looper对象,都与一个消息队列(MessageQueue)相对应,同时也与一个线程(Thread)相对应。

       当我们调用Looper的prepare()方法的时候,执行如下代码:

public static void prepare() {
    prepare(true);
}
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));
}

       从上面的代码可以看出,当执行了Looper.prepare()之后,会先调用ThreadLocal的get方法,判断是否已经存在以当前线程为键的键值对,如果已经存在,则抛出异常 “Only one Looper may be created per thread” 。如果不存在,则执行 sThreadLocal.set(new Looper(quitAllowed)) ;新建一个Looper对象,存入ThreadLocal中。

private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}

       可以看出,创建Looper对象的同时,新建了一个MessageQueue对象,赋值给Looper对象的mQueue属性,将当前线程,赋值给Looper的mThread属性。

2. 接下来执行

    handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    Log.d("TTTT", "handleMessage:" + Thread.currentThread().getName());
                    int i = msg.what;
                    Log.d("TTTT", "收到了消息对象:" + i);
                }
            };

       实例化一个Handler对象,执行其handleMessage方法,查看Handler的源码,路径:sources\android-19\android\os\Hnadler.java

       可以看到Handler类有如下成员变量

    final MessageQueue mQueue;
    final Looper mLooper;
    final Callback mCallback;
    final boolean mAsynchronous;
    IMessenger mMessenger;

       找到其Handler的构造方法

    public Handler() {
        this(null, false);
    }
        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();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can‘t create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

       调用了Looper的 myLooper() 方法赋值给mLooper

    mLooper = Looper.myLooper();

       我们查看Looper.java

    public static Looper myLooper() {
        return sThreadLocal.get();
    }

       发现将当前线程为键的Looper对象从ThreadLocal中取出并返回,所以,在创建Handler对象的时候,Handler对象的拿到了之前创建的Looper对象

  if (mLooper == null) {
    throw new RuntimeException(
                "Can‘t create handler inside thread that has not called Looper.prepare()");
  }

       如果拿到的Looper对象为空,则抛出异常 “Can‘t create handler inside thread that has not called Looper.prepare()” 告知用户在没有调用Looper.preapre()之前,不能创建Handler对象。

    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;

       然后将Looper对象的mQueue给Handler的mQueue。

       这样,就将Thread、Handler、Looper、MessageQueue联系起来了。

 

  

 

 

 

Android笔记(三十三) Android中线程之间的通信(五)Handle、Looper和MessageQueue

标签:

原文地址:http://www.cnblogs.com/xs104/p/4819967.html

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