Android Handler机制简介及双线程通信

一. Handler作用

大多数博客上描述的Handler作用是线程间通信,这个描述其实不算准确,因此一度让我困惑于一个问题,如果只是实现线程间的通信,我在一个线程中设置另一个线程的回调,也能实现通信,为什么要用Handler?

于是看了下SDK上Handler类的解释:

翻译过来就是:

Handler有两个主要用途:

(1)调度消息和在未来某个时间点执行的运行库;

(2)入队一个在不同线程上执行的操作。

很明显,Handler的作用更多在于消息调度和切换执行线程。

 

二. Handler简介

提到Handler机制,源码解释网上有很多,基本都分析得很细,这里就不多说了,大概解释一下,Handler ,  Message , MessageQueue,Looper

Handler: 消息发送/接收器,发送的消息实时进入消息队列。

Message: 基于对象池模式的消息载体,内部属性包含发送器Handler,消息延时时间等相关内容。

MessageQueue:基于链表的消息队列,消息入队列时会对消息排序,时间由小到大排序。

Looper: 消息迭代器,用于从消息队列MessageQueue中迭代出有效消息Message,从Message取出Handler,执行Handler的dispatchMessage进行消息分发,最终进入到Runnable的run方法,或Handler的CallBack接口的handleMessage方法。

/**
 * Handle system messages here.
 */
public void dispatchMessage(@NonNull Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

三. 基于Handler机制,实现切换执行线程

MainActivity.class简单示例代码如下:

Thread1 t1;
Thread2 t2;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
        
        ......//省略部分代码

        t1 = new Thread1();
        t2 = new Thread2();
        t1.setName("Thread1");
        t2.setName("Thread2");
        t2.start();
        t1.start();
}


class Thread1 extends Thread implements Handler.Callback {

        private Handler handler;
        @Override
        public void run() {
            super.run();
            do{
                try {
                    sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Logger.d("Thread1 run t2.isStart() = " + t2.isStart());
            }while (!t2.isStart());
            Looper.prepare();
            handler = new Handler(Looper.myLooper(),this);
            Message message = Message.obtain();
            message.what = 1;
            message.obj = "send from Thread1";
            t2.getHandler().sendMessageDelayed(message,1000);
            Looper.loop();
        }

        public Handler getHandler() {
            return handler;
        }

        @Override
        public boolean handleMessage(@NonNull Message msg) {
            Logger.d("Thread1 ThreadName " + ((String) msg.obj) + " , data = " + msg.what + " ,currentThread = " + Thread.currentThread());
            Message message = Message.obtain();
            message.what = msg.what + 1;
            message.obj = "send from Thread1";
            t2.getHandler().sendMessageDelayed(message,1000);
            return false;
        }
    }

    class Thread2 extends Thread implements Handler.Callback {
        private Handler handler;
        boolean isStart = false;
        @Override
        public void run() {
            super.run();
            Looper.prepare();
            handler = new Handler(Looper.myLooper(),this);
            isStart = true;
            Looper.loop();
        }
        public Handler getHandler() {
            return handler;
        }

        @Override
        public boolean handleMessage(@NonNull Message msg) {
            Logger.d("Thread2 ThreadName " + ((String) msg.obj) + " , data = " + msg.what + " ,currentThread = " + Thread.currentThread());
            Message message = Message.obtain();
            message.what = msg.what + 1;
            message.obj = "send from Thread2";
            t1.getHandler().sendMessageDelayed(message,1000);
            return false;
        }

        public boolean isStart() {
            return isStart;
        }
    }
按照以上代码执行,结果如图所示:

从上图可以看出:在线程Thread1上创建的消息,发送后实际执行在Thread2上,反之亦如此。

若此时使用的不是handler而是线程实例直接回调线程方法,以第一条日志为例,则此时的第一条日志的currentThread将会是Thread1而非Thread2 ,  由此可见,Handler入队了一个在不同线程上执行的操作.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值