如何高效学习Handler?

本文详细探讨了Android主线程中的Handler和Looper的创建、工作机制,以及如何使用Handler发送延时消息。通过图解和代码剖析,揭示了Handler与Looper如何实现线程间的通信,包括MessageQueue的作用和消息分发过程。

主线程创建及简要代码说明图:

生产消费模型理解UI线程工作原理图:

三.如何使用Handler?


Handler handler = new Handler(){

@Override

public void handleMessage(final Message msg) {

//这里接受并处理消息

}};

//发送消息

handler.sendMessage(message);

handler.post(runnable);

实例化一个Handler并重写 handleMessage方法, 然后在使用的地方调用它的send以及 post系列方法就可以了, 简单易用,并支持延时消息。

四.实现原理


图解原理:

代码实现原理:

1.创建Handler, 将Handler与Looper关联起来:

public Handler(Callback callback, boolean async) {

//检查当前的线程是否有 Looper

mLooper = Looper.myLooper();

if (mLooper == null) {

throw new RuntimeException(

“Can’t create handler inside thread that has not called Looper.prepare()”);

}

//Looper 持有一个 MessageQueue

mQueue = mLooper.mQueue;

}

实现说明:

1).将Handler与Looper关联起来,创建Handler之前一定要先创建Looper,否则会报错;

由于ActivityThread(主线程)在main()方法中已通过Looper.prepareMainLooper()创建了Looper对象,

故能通过Looper.myLooper()获取Looper对象;

2).Looper会持有一个MessageQueue;

3).一个完成的Handler应该如下:

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提供了Looper.prepare()方法来创建Looper,

并会借助ThreadLocal来实现与当前线程的绑定功能;

Looper.loop()则会开始不断尝试从MessageQueue中获取 Message,并分发给对应的Handler;

即Handler跟线程的关联是靠 Looper 来实现的。

2.通过send及post系列方法发送Message, 然后将Message添加进入MessageQueue

通过send及post系列方法发送消息,最终会走到 MessageQueue.enqueueMessage(Message,long)方法。

1).Message:

Message是线程间通信的信息载体,包含一些特定的描述和任意的附加数据;

Message具有setData()和getData()方法,它们分别可获取和添加用Bundle对象封装的数据,

这些数据就是线程之间相互传递的数据;

Message对象不建议使用new Message()来获取,可通过Messa.obtain()或Handler的obtainMassage()方法获取;

obtain()可从全局的Message Pool(消息池)中返回一个Message对象;

Message Pool(消息池):是android系统专门用来管理消息的一种机制,

主要是为了避免Message对象频繁的创建销毁带来的开销, 故使用消息池来维护这些对象,

对象使用后可重新放到池中被重新使用,它的大小是10;

2).MessageQueue:

MessageQueue是一个由Message组成的队列,是一个偏底层的类,

它包含的Message由Looper对象分发出去;

Message并不是直接添加进消息队列的, 而是通过与Looper相关的MessageQueue.IdleHandler对象添加;

可使用Looper.myQueue()方法取回当前线程的消息队列;

MessageQueue是通过next()方法获取Message的;

//MessageQueue

Message next() {

//

for (;😉 {

nativePollOnce(ptr, nextPollTimeoutMillis);

synchronized (this) {

//

Message msg = mMessages;

//

if (msg != null) {

if (now < msg.when) {

nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);

} else {

//

return msg;

}

}

//

}

}

图解MessageQueue处理Message:

3.通过Looper.loop()死循环对Message进行获取和分发

Looper:是线程用来运行消息循环的,线程本身无消息循环,

需要调用Looper.prepare()创建Looper对象,然后调用Looper.loop()去处理消息;

Android中系统在启动主线程时会自动为之建立一个Looper对象;

Looper对象通过消息队列来存放消息和事件,一个线程只能有一个Looper,对应一个消息队列;

默认情况下,Handler会与其定义时所在的线程的Looper绑定,如在UI线程中定义,则与UI线程的Looper绑定;

//Looper.loop()源码解读:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值