Handler Looper MessageQueue

本篇博客介绍Handler与Looper的关系,可能大家都有用过Handler实现跨线程的通信(比如子线程处理完耗时,使用handler发送消息给主线程进行UI更新操作),但是里面的原理大家都清楚吗?本篇博客将和大家一起了解里面的机制。


Handler

我们首先来看下api的介绍
A Handler allows you to send and process {@link Message} and Runnable objects associated with a thread’s {@link MessageQueue}. Each Handler instance is associated with a single thread and that thread’s message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it – from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.

There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.
简单翻译下:Handler可以让我们把Message或者Runnable对象发送到与之关联的消息队列中,每个Handler实例都与单一的线程,以及该线程的消息队列对应。当你创建一个Handler的时候,它就与该线程/创建它的线程中的消息队列进行绑定。从这点来说,它可以传递 message和runnable到消息队列,然后在消息队列中执行任务。
上面加粗部分的介绍,可能是我因为不过关,我总觉得描述的不够准确,后面会有例子说明这点。

Looper

Looper的设计使用了ThreadLocal, 保证了每个线程最多只能有一个对应的looper,通过Looper.prepare(),可以为当前线程绑定一个looper。Looper中持有一个messageQueue, handler发送的消息都会进到这个messageQueue里,然后进行执行。 handler里发送任务的最终的执行线程,就是looper所绑定的线程。

我们直接上测试代码吧

    Looper looperThread1;
    private void testHandle() {
        new Thread(new Runnable(){
            @Override
            public void run() {
                         Log.d("Tag",
                         Thread.currentThread()+"Looper.prepare");
                Looper.prepare();
                looperThread1 = Looper.myLooper();
                Looper.loop();
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Log.d("Tag", Thread.currentThread()+"Create Handler");
                Handler handler = new Handler(looperThread1);
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        Log.d("Tag", Thread.currentThread()+"handle runnable");
                    }
                });
            }
        }).start();

    }

运行的结果是:

D/Tag: Thread[Thread-146,5,main]Looper.prepare
D/Tag: Thread[Thread-147,5,main]Create Handler
D/Tag: Thread[Thread-146,5,main]handle runnable

这段代码证明了,Handler中发送的message或runnable对象,最终执行的时候,并非一定是在 Handler的创建线程,而是在创建Handler时,在构造方法里传入的 looper所在的线程,只是我们调用无参构造方法时,默认用的是当前线程looper.

如果大家还有不理解的地方可以可以再看看源码,或者留言一起学习讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值