Handler基础

应用程序启动时,会开启一个主线程(即UI线程),用来管理UI,监听用户点击,相应用户并发事件分发。所以主线程不进行耗时操作,否则出现ANR错误。这些耗时操作放到子线程中,由于Android子线程不是安全的,所以只能在主线程中更新UI。Handler就是用来子线程和创建Handler的线程进行通信的。

Handler的作用

1、按照时间计划,在未来某时刻,对处理一个消息或执行某个runnable实例。

2、把一个对另外线程对象的操作请求放入消息队列中,从而避免线程冲突。

Handler的使用

1、发送消息,在不同线程间发送消息通信,使用的方法为sendXXX():

sendEmptyMessage(int),发送一个空消息

sendMessage(message),发送一个message消息

sendMessageAtTime(message ,long),未来某一时间段点发送message消息

sendMessageDelayed(message ,long),延时N ms后发送message消息

 

2、计划任务,在未来执行某任务,使用的方法为postXXX():

post(Runnable),提交计划任务马上执行

postAtTime(Runnable ,long),提交计划任务在未来的时间点执行

postDelayed(Runnable , long),延时N ms提交计划任务

区别:sendXXX()发送的是消息,在handler里面操作UI;而postxxx()发送的是Runnable对象,在Runnable对象里面操作UI

在线程中创建Handler

在线程中创建Handler首先需要保证线程中包含Looper(UI线程中默认包含Looper)。为线程创建Looper的方法:

在线程的run()方法中先调用Looper.prepare()初始化Looper,然后再run()方法最后调用Looper.loop()开始循环处理消息,这样就创建好了Looper。

class MSecondThread extends Thread{
    public Looper looper;
    @Override
    public void run() {
        Looper.prepare();
        looper = Looper.myLooper();
        Looper.loop();
    }
}

这就给子线程创建好了Looper,但是主线程想要给子线程传递消息的话,还需要给Handler指定相应的Looper,方法如下:

mHandler = new MyHadler(mSecondTd.looper){
    @Override
    public void handleMessage(@NonNull Message msg) {
        super.handleMessage(msg);
        Log.d(TAG, Thread.currentThread()+" ");
    }
};

这样就创建了主线程给子线程传递消息的Handler和Looper。但是,这个过程中,在给Handler执行Looper时,经常会遇到Looper没有完成初始化的情况,往往需要采用一些等待之类的操作让子线程的Looper完成初始化,大大降低了效率,所以便有了HandlerThread。

HandlerThread

一种专门用户Handler通信的线程,上述情况使用HandlerThread可以简单快捷的实现,并且不用考虑Looper初始化的问题,例如

mSecondTd = new HandlerThread("HandlerThread");
mSecondTd.start();
mHandler = new Handler(mSecondTd.getLooper()){
    @Override
    public void handleMessage(@NonNull Message msg) {
        super.handleMessage(msg);
        Log.d(TAG, Thread.currentThread().getName());
    }
};

在点击事件中,使用mHandler.sendEmptyMessage(1)发送消息时,打印出来的线程名称为“HandlerThread”。

使用HandlerThread需要注意的是,HandlerThread所创建的子线程不能重写run()方法,否则不会执行HandlerMessage(),因为HandlerMesssage()本身就已经实现了run()。一个Handler在与HandlerThread进行绑定时,发现Looper为空,Handler则会一直等到知道Looper被创建出来为止,然后才继续执行后续的代码。所以我们重写了HandlerThread的run()方法,自然就不会去创建Looper对象了,绑定的相应的Handler就会永远处于等待状态,自然就不会执行handleMessage()了。使用HandlerThread我们不用关心多线程混乱,Looper为空等一系列问题。

Handler通信就是由别的线程使用指定线程的Handler向指定线程发送(sendXXX()\postXXX())消息,然后有指定线程消费消息的通信方式。需要注意的是主线程向子线程发送消息是,子线程需要使用Looper.prapare(),Looper.loop()方法准备创建Looper,并且要给Handler指定Looper。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值