Handler、Looper、ThreadLocal、MessageQueue、Message

来源:互联网 发布:金融数据分析师招聘 编辑:程序博客网 时间:2024/04/29 20:23

先说Looper。

Looper作用是:通过for循环MessageQueue队列中的的Message,然后触发Handler的HandleMessage回调方法。

1、Looper没有公共的构造方法,所以实例化用prepare()方法。

2、Looper没有getLooper()方法。获取自身实例,是静态的公共方法myLooper(); 

3、Looper的核心方法是loop(); 执行无限for循环【for(;;)】


Looper实例化:

在prepare()中不但有new Looper(); 还应该注意到私有构造Looper()中还有new MessageQueue();方法。


再说Handler。

Handler作用是:通过sendMessage方法将Message对象添加到MessageQueue中。

1、Handler的构造方法中,获取到了Looper对象(Looper.myLooper(),注意并没有实例化Looper),通过Looper对象获取到MessageQueue对象(looper.mQueue)。

2、Handler的核心方法是sendMessage。sendMessage(msg)调Handler的入队方法enqueueMessage(msg)方法。Handler的enqueueMessage(msg)方法,将Handler对象赋给了msg.target属性,然后又调了MessageQueue对象的入队方法enqueueMessage(msg),MessageQueue的enqueueMessage(msg)方法将msg添加到队列的最顶端。

3、Handler的公共方法dispatchMessage(msg),是在Looper的loop方法中调用。dispatchMessage方法中调用了mCallback.handleMessage(msg)回调方法。

另外,注意Handler.java的dispatchMessage方法:

public void dispatchMessage(Message msg) {        if (msg.callback != null) {            handleCallback(msg);        } else {            if (mCallback != null) {                if (mCallback.handleMessage(msg)) {                    return;                }            }            handleMessage(msg);        }    }
private static void handleCallback(Message message) {        message.callback.run();    }
可见,如果Message对象的callback属性不为空,则直接执行msg.callback.run()方法。

那什么时候msg.callback不为空呢?
我们看一下Handler.java的post(Runnable r)方法:

public final boolean post(Runnable r)    {       return  sendMessageDelayed(getPostMessage(r), 0);    }
private static Message getPostMessage(Runnable r) {        Message m = Message.obtain();        m.callback = r;        return m;    }
所以啊,mHandler.post(runnable); 并不需要handleMessage()回调方法来接收处理,人家直接在runnable的run方法里处理了。


再说ThreadLocal<T>。

ThreadLocal<T>作用是:通过set(T)方法,调用Thread中的ThreadLocal.Values对象来存储T对象。

1、ThreadLocal.Values类,有put方法,所以可以将Values理解为HashMap。

2、ThreadLocal本身并不存储Values对象或T对象,它是通过set方法通知currentThread的Thread对象中的成员变量ThreadLocal.Values localValues来存储T对象。

3、Looper的prepare方法实例化Looper并非简单的new Looper(),而是通过sThreadLocal.set(new Looper())来实现实例化,这样做可以解决多线程相同变量访问冲突问题(类似于synchronized用法)。同样Looper.myLooper()方法也是通过sThreadLocal.get()方法获取的Looper对象,而非简单的将Looper对象存为成员变量来用于获取对象。


另外,MessageQueue是个先进先出队列;Message类就是一个实体类,没什么特别的。

0 0
原创粉丝点击