Android异步消息机制

来源:互联网 发布:网络的特点有哪些 编辑:程序博客网 时间:2024/05/22 15:28

首先是要明白,Android UI 是线程不安全的,在 UI 线程中不可以执行耗时操作,在子线程中不可以更新 UI。


所以就需要我们在子线程去做耗时操作,在 UI 线程中去更新UI。


异步消息

Handler Looper Message MessageQueue


首先明白这个类的作用

Handler 用来操作消息的(包括,发送和处理)

Looper 用来控制消息的循环,一个线程对应一个Looper

Message 封装消息的实体

MessageQueue 消息队列,用来存放消息的 一个Looper对应一个消息队列


明白Handler使用的条件

在使用Handler之前,必须调用Looper.prepare();这个方法。否则会抛一个运行时异常:Can't create handler inside thread that has not called Looper.prepare()

剖析

在Handler的构造方法中

通过

mLooper = Looper.myLooper();

得到一个Looper对象

进入到myLooper()方法

return sThreadLocal.get();         sThreadLocal 是一个 存放 Looper 的 ThreadLocal 

这样就从当前线程当中去取一个Looper对象

如果sThreadLocal 为null 则得不到 Looper对象


现在再来看Looper.prepare();

if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");

}
sThreadLocal.set(new Looper());          new一个Looper对象存放在ThreadLocal 当中

在这个方法中解决了俩个问题

1.一个线程当中只对应一个Looper对象

2.在使用Handler之前必须调用Looper.prepare();


这个时候,好多人会有一个疑问,就是在UI线程里面使用Handler的时候,也没有使用Looper.prepare();这个方法

android在启动的时候,其实首先是先去调用UI线程 ActivityThread 然后通过main()入口,启动应用程序

在main()方法中

Looper.prepareMainLooper(); 

prepareMainLooper()方法中

prepare();  

setMainLooper(myLooper());  

if (Process.supportsProcesses()) {  

myLooper().mQueue.mQuitAllowed = false;   

}

所以在UI线程中,系统已经为我们设置好了Looper对象


Handler 在 发送消息的时候 ,除了使用sendMessageAtFrontOfQueue()这个方法,其他方法最后都会调用sendMessageAtTime() 这个方法去发送消息

sendMessageAtTime()  接收俩个参数

sendMessageAtTime(Message msg, long uptimeMillis)

msg 就是我们要发送的消息

uptimeMillis 是发送消息的时间 = 系统当前时间 + 发送消息延时的时间


在这个方法里面实现的消息的入队操作enqueueMessage()

在这个方法中

系统并没有把所有消息都存放在集合中,只是使用了一个变量来记录当前要发送的消息。


出队

Looper.loop()

通过队列的操作,不断的通过next() 得到消息

如果消息不为null

msg.target.dispatchMessage(msg); 

msg.target 其实就是 Handler 对象


dispatchMessage() 方法中,判断回调接口是否为空

不为空

调用mCallback.handleMessage(msg)

0 0