1:处理消息的手段————Handler、Looper、MessageQueue我们知道Android有主线程(UI线程)和子线程,所有的消息队列都会封装成消息在主线程中来处理,为了保证主线程不退出,消息放在一个死循环中如图所示:UI线程的循环是在ActivityThread.main方法中创建, ActivityThread,顾名思义,UI线程,也是Android整个应用的入口,代码如下所示:public static void main(String[] args) {
//代码省略
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();//1:创建消息循环
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();//线程UI的Handler
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();//2:执行消息循环
throw new RuntimeException("Main thread loop unexpectedly exited");
}
消息运转的关键————Handler(必须在主线程中创建)创建示例如下:class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
// 更新UI
}
}
MyHandler mhandler = new MyHandler();
new Thread(){
public void run{
//耗时操作
mhandler.sendEmptyMessage(123);
};
}.start();
每个Handler都会关联一个消息队列,消息队列又封装在Looper中,每个Looper又关联一个线程,说白了,Handler就是一个消息处理器,将消息post给消息队列,再由对应的线程逐个取出。那么问题来了,消息队列是如何创建的呢?
答:就是ActivityThread.main中 Looper . prepareMainLooper (); 方法我们先看如下源码:public Handler(Callback callback, boolean async) {
//代码省略mLooper = Looper.myLooper();//获取Looper
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;
}
Handler构造里面Looper.getLooper()来获取Looper对象并与之关联,它是怎么工作的呢?下面来看看myLooper里面代码怎么实现的:public static Looper myLooper() {
return sThreadLocal.get();
}
接着往下看:public static void prepareMainLooper() {
prepare(false);//见下
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException(
"The main Looper has already been prepared.");
}
sMainLooper = myLooper();//设置UI线程的Looper为当前Looper对象
}
}
// 为当前线程设置一个Looper
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是通过 sThreadLocal . get (); 获取到的,Looper是什么时候存到 sThreadLocal中的呢?如下:
这样队列就与线程关联上了前面讲到Handlder与Looper的关联,所以Handler最终和队列、线程就关联上了这也就解释清楚了:更新UI的时候为什么必须要在主线程中创建Handler,就是因为Handler要与主线程的消息队列进行关联
关联明白了,那么如何循环队列呢:答:通过Handler来Post消息给消息队列那么消息是如何被处理的呢?我们明天继续分解
Android中Handler源码解析(一)
最新推荐文章于 2024-09-06 22:40:28 发布