如何正确使用(在子线程中) 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, 我没使用过不做多说, 感兴趣的可以看下源码

猜你喜欢

转载自blog.csdn.net/qq_27070117/article/details/81183118
今日推荐