Android中异步消息处理机制
来源:互联网 发布:网络优化大师下载 编辑:程序博客网 时间:2024/04/28 22:05
1. Thread Local Storage (线程局部存储)
我们通过位于android.os包下的Looper.class源码可以看到成员变量区有一个线程局部变量sThreadLocal,该类的作用是线程局部存储?那么是线程局部存储TLS?这个问题可以从变量作用域的角度来理解。
变量的常见作用域一般包括以下几种。
- 函数内部变量。其作用区域是该函数,即每次调用该函数,该变量都会重新回到初始值。
- 类内部的变量。其作用就是该类所产生的对象,即只要该对象没有被销毁,则对象内部的变量则一直保持。
- 类内部的静态变量。其作用是整个进程,即只要在该进程中,该变量的值就会一直保持,无论使用多少类来构造这个对象,该变量只有一个赋值,且一直保持。
ThreadLocal内部其实是使用弱引用WeakReference来存储当前线程对象,但是不同的线程有不同的ThreadLocal对象,因此会有一个用于区别的id,由此内部封装了一个静态内部类Values,这个类就相当于一个map,存储了每一个线程的实例的值。
sThreadLocal在prepare()函数被调用的时候就进行了一次赋值,即构造一个新的Looper对象存储到本地线程局部变量中,当然一个线程只能有一个Looper对象,否则会抛出如下图所示的异常。
prepare()我们已经说过了,下面说下prepareMainLooper()。
prepareMainLooper(),由方法注释我们可以知道,这个应用程序的mainlooper对象是由android环境创建的,所以你自己永远没必要调用这个函数。
2. Looper
我们可以从类注释来了解Looper类的作用到底是干什么的。
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare
in the thread that is to run the loop, and then loop
to have it process messages until the loop is stopped.
Most interaction with a message loop is through the Handler
class.
This is a typical example of the implementation of a Looper thread, using the separation of prepare
and loop
to create an initial Handler to communicate with the Looper.
class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } }
Looper类的作用就是给在线程内部创建一个消息循环,当然线程自身内部是没有一个消息循环机制;在run()函数首行调用Looper.prepare(),即使创建了一个消息循环队列,然后在run函数尾行调用Looper.loop()则开始处理消息直到消息循环停止。
大多数消息循环的交互是通过Handler类进行的。
3. Handler
这里我们只从消息循环机制角度来分析这个Handler。首先看Handler的构造函数
/**
* Default constructor associates this handler with the queue for the
* current thread.
*
* If there isn't one, this handler won't be able to receive messages.
*/
public Handler() {
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());
}
}
//从TLS(局部线程存储)中取出已经存放好的Looper对象
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
//将Looper对象中的MessageQueue赋值给Handler中的对象
mQueue = mLooper.mQueue;
mCallback = null;
}
* Default constructor associates this handler with the queue for the
* current thread.
*
* If there isn't one, this handler won't be able to receive messages.
*/
public Handler() {
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());
}
}
//从TLS(局部线程存储)中取出已经存放好的Looper对象
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
//将Looper对象中的MessageQueue赋值给Handler中的对象
mQueue = mLooper.mQueue;
mCallback = null;
}
然后我们在从使用的角度分析,这里我只从异步处理UI界面分析。
我们(程序员)通过 Handler调用sendMessage()函数在线程内部向UI主线程发送一个Message对象,该Message对象会依次通过Handler中的函数
sendMessage(...) -> sendMessageDelayed(...) -> sendMessageAtTime(...) 最终会通过sendMessageAtTime发送消息对象。
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
msg.target = this;
//将消息对象加入到消息队列
sent = queue.enqueueMessage(msg, uptimeMillis);
}
else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}
然后我们在来看看enqueueMessage进行了什么操作。
final boolean enqueueMessage(Message msg, long when) {
...
if (needWake) {
nativeWake(mPtr);
}
...
}
nativeWake是一个java本地方法,这里涉及了消息机制中的Sleep-Wakeup机制,关于如何唤醒Looper线程的动作,这里不做赘述,其最终就是调用了 native层的Looper的wake函数,唤醒了这个函数之后,就开始进行消息循环
0 0
- Android中异步消息处理机制
- android中异步消息的处理机制
- Android中异步消息处理机制
- Android中异步消息处理机制
- Android异步消息处理机制
- Android异步消息处理机制
- Android异步消息处理机制
- android异步消息处理机制
- Android异步消息处理机制
- android异步消息处理机制
- Android异步消息处理机制
- Android异步消息处理机制
- Android 异步消息处理机制
- Android异步消息处理机制
- Android异步消息处理机制
- Android异步消息处理机制
- Android 异步消息处理机制
- Android异步消息处理机制
- android l 中AppWidgetService的启动
- git rm简介
- javascript删除html结点操作
- javamail添加邮件附件时德文、中文乱码的问题
- Aix 上NFS详细介绍
- Android中异步消息处理机制
- UILabel 行间距方法 可直接调用
- UML资料整合
- 盒子模型1
- EP4: 无偏博弈和数学游戏
- PHP程序员的技术成长规划
- CCNode的tag
- 命令行下打包并导出ipa测试
- C# 解压缩文件帮助类