Android学习笔记(十四) Handler理论补充

一、如何下载Android源码

  在SDK Manager中选中Sources for Android SDK。

二、ThreadLocal初步介绍

  1)执行ThreadLocal对象(static final ThreadLocal sThreadLocal)的set(Object obj)方法,将会向存入一个以当前线程为键的键值对。

  2)执行ThreadLocal对象的get()方法,将会根据当前线程对象为键,取出与之对应的值。

  在之前提到的Looper方法调用中:

  执行Looper.prepare时,系统会生成一个Looper对象,然后和当前线程通过ThreadLocal存储(set)起来。生成Handler对象时,又根据线程名将Looper对象取(get)出来,然后赋值给Handler对象的mLooper成员变量。因此Looper和Handler的关系是通过ThreadLocal联系起来的

  生成Looper对象时会生成一个与之相对应的MessageQueue对象。之后生成Handler对象时,将Looper对象和MessageQueue对象都赋值给Looper的成员变量。

三、什么是Message对象的target变量

  实际上是生成Message对象时使用的Handler对象。

  一个Handler对应一个Looper对象,一个Looper对象对应一个MessageQueue对象,使用Handler生成Message,所生成Message对象的target属性,就是该Handler对象(发送Message的Handler对象)。

四、Handler的post(Runnable)方法

class TestThread extends Thread{
    @Override
    public void run(){
        Runnable r = new Runnable(){
            @Override
            public void run(){
                String currentThreadName = Thread.currentThread().getName();
                System.out.print("当前线程的名称是:"+currentThreadName);
            }
        };
        handler.post(r);
        //将Runnable对象放到MessageQueue里。
        
        //在主线程中生成Handler对象,然后取出r对象。
        //打印出来的结果是“当前线程的名称是:main
    }
}

这里有两个问题:

1)如何将Runnable对象放在MessageQueue里?

2)Looper对象(主线程)从消息队列中取出了r对象之后做了些什么?

 

第一个问题:

将Runnable对象放到MessageQueue里,实际上是生成了一个Message对象,并将r赋值给Message对象的callBack属性,然后再将Message对象放在消息队列中。

第二个问题:

Looper对象(主线程)从消息队列当中取出了r对象(根据第一问,此处应是携带r的Message对象)。我们可以猜测,取出r对象后-->Thread t = new Thread(r)-->t.start()。但是根据结果可以看出,该猜测错误。

正确情况是:取出Message对象之后调用了dispatchMessage()方法,然后判断Message的callback属性是否为空。此时callBack属性有值,所以执行了handleCallback(Message msg),在该方法中直接执行了msg.callback.run()

注意:直接执行run()方法时,不会开辟一个新线程,而是直接执行run()里面的内容。(这在(四)区分start()和run()中提到过)。

所以在run()方法里可以写上更改UI的代码。

posted @ 2017-02-14 13:40  viaduct  阅读(181)  评论(0编辑  收藏  举报