android开发步步为营之115:HandlerThread的简单用法

本文详细介绍了HandlerThread的工作原理及其与主线程交互的方式。通过一个具体的示例应用程序,展示了如何使用HandlerThread来执行后台任务,并与UI主线程进行消息通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       HandlerThread继承至Thread。区别是HandlerThread内部自己创建了Looper,Looper又创建了MessageQueue,looper.loop内部不停的在检查messageQueue里面是否有新消息Message。有的话就交给message的target即handler去处理。通过查看HandlerThread的源代码。主要是在这个run方法里面

 @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }




       new一个Handler的时候将新创建的HandlerThread的Looper当做参数传递给自己,那么这个handler就和当前的HandlerThread关联在一起了,handler sendMessage的时候,其实就把消息发送给给looper里面创建的MessageQueue里面了。当前的handler就不是运行在UI主线程里面了,已经属于HandlerThread子线程了。下面给出一个简单的demo。

package com.figo.study.activity;

import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;

import com.figo.study.R;

import java.util.Random;


public class HandlerThreadActivity extends AppCompatActivity {
    private HandlerThread mHandlerThread;
    private Handler mHandlerBindtoHandlerThread;
    private boolean isScheduled;
    private static final int WHAT = 123;
    //测试产生一个随机数
    int mResult = 0;
    //默认运行在主线程,因为使用了默认的looper是ui主线程创建的
    Handler mHandlerBindToUi = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 1:
                    //更新ui,这里就简单弹个消息了
                    Toast.makeText(HandlerThreadActivity.this, "耗时操作完成,这里更新ui啊,mResult=" + mResult, Toast.LENGTH_SHORT).show();
                    break;
                default:
                    break;
            }

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_thread);
        findViewById(R.id.btn_test).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //方法一:使用handlerThread
                useHandlerThread();

                //方法二:使用handler+thread
                //new Thread(new MyRunnable()).start();
            }
        });

    }

    @Override
    protected void onResume() {
        super.onResume();

    }

    @Override
    protected void onPause() {
        super.onPause();
        //停止查询
        isScheduled = false;
        mHandlerBindtoHandlerThread.removeMessages(WHAT);
    }


    //方法一:使用HandlerThread
    private void useHandlerThread() {
        mHandlerThread = new HandlerThread("check-message-coming");
        mHandlerThread.start();
        mHandlerBindtoHandlerThread = new Handler(mHandlerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case WHAT: {
                        //当前handler已经运行在新线程mHandlerBindtoHandlerThread,所以这里可以运行耗时任务
                        loadData();

                        if (isScheduled) {
                            mHandlerBindtoHandlerThread.sendEmptyMessageDelayed(WHAT, 3000);//可设置延迟多少毫秒后继续执行耗时任务

                        }
                    }
                    break;
                    default:
                        break;
                }
            }
        };
        //发送一条消息去执行耗时任务
        mHandlerBindtoHandlerThread.sendEmptyMessage(WHAT);

    }


    //方法二:使用Handler+Thread

    class MyRunnable implements Runnable {
        @Override
        public void run() {
            //执行耗时任务
            loadData();
        }

    }

    //耗时任务,加载数据
    private void loadData() {
        try {
            //sleep模拟耗时操作,请使用你的耗时任务来代替Thread.sleep()
            Thread.sleep(12000l);
            Random r = new Random();
            mResult = r.nextInt(10000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //执行完成通知ui主线程更新页面

        mHandlerBindToUi.sendEmptyMessage(1);
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        //释放资源,避免looper一直在执行无限循环
        mHandlerThread.quit();
    }
}

        使用handlerThread的优点是方便子线程和ui主线程即ActivityThread之间的消息通信。比如最近在做的一个表情相机,在相机预览获取到数据的时候在onPreviewFrame方法里,这是运行在主线程的,我直接使用mHandlerBindtoHandlerThread发条消息通知handlerThread子线程去执行耗时的人脸识别方法。识别成功后,我又使用在主线程创建的handler,发条消息出去,通知ui主线程更新页面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值