如何正确使用(在子线程中) Looper 和 Handler

如何正确使用(在子线程中) Looper 和 Handler

  网上关于 Looper 解析相关的文章非常多, Handler 的使用相信所有做Android开发的都熟的不能再熟了, 那么本文存在的意义还有什么呢? 当然我不会介绍什么 Looper Handler 消息机制, 如果不了解 Handler Message 消息机制请自行百度.
   要理解以下内容首先需要能够正常使用Handler, 以及了解 Looper 机制, 首先说下Looper中几个重要方法:

{
    Looper.prepare();// Looper 初始化, 使用Handler Looper消息机制必须要初始化Looper
    Looper.myLooper();// 获取当前调用线程中ThreadLocal缓存的Looper对象
    Looper.loop();//Handler机制的大前提, 使调用线程进入死循环, 没错, Android中主线程一直都在死循环

    //getLooper()是Handler中的方法, 获取Handler中缓存的Looper对象, 使用Handler无参构造创建将缓存调用线程
    //Looper对象, 使用Handler(Looper looper)构造创建将缓存传入的Looper对象;

    mHandler.getLooper().quit();//终止 Looper.looper() 死循环, 执行 quit后Handler机制将失效, 执行时如
    //果MessageQueue中还有Message未执行, 将不会执行未执行Message, 直接退出, 调用quit后将不能发消息给Handler

    mHandler.getLooper().quitSafely();//Android4.3, API Level 18 后加入的方法, 作用同 quit(), 但终止
    //Looper之前会先执行完消息队列中所有非延时任务, 调用quit后将不能发消息给Handler
}

   子线程使用Looper非常简单, 话不多少, 继续上代码:

    Handler mHandler;
        new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();//Looper初始化
                //Handler初始化 需要注意, Handler初始化传入Looper对象是子线程中缓存的Looper对象
                mHandler = new Handler(Looper.myLooper());
                Looper.loop();//死循环
                //注意: Looper.loop()之后的位置代码在Looper退出之前不会执行,(并非永远不执行)
            }
        }).start();

  以上代码已经在子线程初始化了 Looper和 Handler, 只有我们就可以在其他线程(主或子线程)中使用Handler来给当前子线程发消息了:

    Handler mHandler;
    int count = 5;
    public void main(String[] args){
        new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();//Looper初始化
                //Handler初始化 需要注意, Handler初始化传入Looper对象是子线程中缓存的Looper对象
                mHandler = new Handler(Looper.myLooper());
                Looper.loop();//死循环
                //注意: Looper.loop()之后的位置代码在Looper退出之前不会执行,(并非永远不执行)
            }
        }).start();
        //主线程 注意此处在主线程延时一秒才给子线程发消息是因为子线程创建需要时间, 立刻发消息Handler还么没准备好, 会抛出异常.
        Log.log("count: ---> " + " ThreadName: " + Thread.currentThread().getName());
        //MainThread是我自定义的一个类, 内部缓存了一主线程Handler
        MainThread.getHandler().postDelayed(new Runnable() {
            @Override
            public void run() {
                //使用子线程中的mHandler给子线程发一个延时消息
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if(count >= 0) {
                            //打印当前线程名
                            Log.log("count: ---> " + count+" ThreadName: "+Thread.currentThread().getName());
                            count--;
                            //继续给子线程发消息
                            mHandler .postDelayed(this,1000);
                        }else if(count >= -10){
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                                mHandler.getLooper().quitSafely();
                            }else {
                                mHandler.getLooper().quit();
                            }
                            Log.log("quit: count: ---> " + count+" ThreadName: "+Thread.currentThread().getName());
                            count--;
                            //继续给子线程发消息
                            mHandler .postDelayed(this,1000);
                        }
                    }
                },1000);
            }
        },1000);
    }

执行后打印Log如下: 很明显我们在子线程中使用Handler的方式是正确的
这里写图片描述
据说HandlerThread封装了子线程+Handler, 我没使用过不做多说, 感兴趣的可以看下源码

  • 9
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在Android开发,主线程(也被称为UI线程)负责处理与用户交互的操作,例如响应用户的点击事件、更新UI界面等。而线程则是用于执行一些耗时的任务,比如网络请求、数据库操作等。 为了实现在子线程更新UI界面的需求,Android提供了Handler和Looper机制。Looper是一个负责循环消息队列的类,它负责从消息队列取出消息,然后将其分发给对应的Handler进行处理。 在子线程使用Looper来处理消息时,需要首先调用Looper.prepare()方法来准备Looper,然后调用Looper.loop()方法来循环处理消息,直到Looper.quit()被调用停止循环。在调用Looper.loop()之前,需要先创建一个Handler的实例,并将其与当前线程的Looper关联起来。这样,线程的Looper才能将消息分发给相应的Handler进行处理。可以使用Handler的post()、sendMessage()等方法来向线程的消息队列发送消息。 使用线程的LooperHandler机制,可以实现在子线程更新UI界面的需求,避免在主线程执行耗时操作导致界面卡顿的问题。然而,需要注意的是,在子线程使用LooperHandler时要避免在UI界面的更新操作过于频繁,以免影响用户体验和性能。 总结一下,Android在子线程使用LooperHandler的目的是为了实现在子线程更新UI界面的需求,通过创建Looper实例并循环处理消息,将消息分发给对应的Handler进行处理。这样就能在子线程更新UI界面,提高程序的性能和用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值