Android中Handler源码解析(一)

 
 
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消息给消息队列
那么消息是如何被处理的呢?我们明天继续分解
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值