HanlderThread继承自Thread,它的run()中通过Looper.prepare()创建了消息队列,并通过Looper.loop()开启了消息循环,这样我们就可以在HandlerThread中创建Handler了(对Android消息机制不熟悉的可以参考Android消息机制(Handler、Looper、MessageQueue),从而外界通过Hanlder通知HandlerThread来执行一个具体的任务。

1.HanlderThread的使用

下面来简单的演示一下HandlerThread的使用,布局文件没有任何作用所以就不贴出来了

public class MainActivity extends AppCompatActivity {    /**     * 工作消息标志     */    private final static int MSG_WORK = 0x01;    private Handler       mHandler;    private HandlerThread mHandlerThread;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mHandlerThread = new HandlerThread("HandlerThread");        mHandlerThread.start();     //开始线程        mHandler = new Handler(mHandlerThread.getLooper()) {            @Override            public void handleMessage(Message msg) {                try {                    Thread.sleep(3000);     //模拟延时操作                    Log.e(Thread.currentThread().getName(), (int) (Math.random() * 3000 + 1000) + "");                    mHandler.sendEmptyMessageDelayed(MSG_WORK, 1000);   //延时一秒发送工作消息                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        };        mHandler.sendEmptyMessage(MSG_WORK);    //发送工作消息,触发消息Handler执行    }    @Override    protected void onDestroy() {        super.onDestroy();        mHandler.removeMessages(MSG_WORK);      //移除队列中为执行的工作消息        mHandlerThread.quit();      //退出线程    }}

下面是logcat的输出结果:

07-08 14:08:19.522 1404-1619/com.zhong.handlerthread E/HandlerThread: 190207-08 14:08:23.523 1404-1619/com.zhong.handlerthread E/HandlerThread: 310807-08 14:08:27.525 1404-1619/com.zhong.handlerthread E/HandlerThread: 363007-08 14:08:31.527 1404-1619/com.zhong.handlerthread E/HandlerThread: 104107-08 14:08:35.528 1404-1619/com.zhong.handlerthread E/HandlerThread: 284507-08 14:08:39.529 1404-1619/com.zhong.handlerthread E/HandlerThread: 387107-08 14:08:43.531 1404-1619/com.zhong.handlerthread E/HandlerThread: 176707-08 14:08:47.533 1404-1619/com.zhong.handlerthread E/HandlerThread: 2593

每隔4s输出当前线程的名称和一个随机数,通过线程名称我们可以发现这段代码确实是在HandlerThread线程中执行的。上面的程序毫无使用价值,只是为了演示HandlerThread的使用,HandlerThread是一个很有用的类,Android中的IntentService中就封装了一个HanderThread(后续再做介绍,这里就不做解释了)

注意:

HandlerThreadrun方法是一个无限循环,Looper.loop()会不断循环取消消息交给Handler处理,没有消息是会阻塞,所以当不需要使用HandlerThread时用调用它的quit()quitSafely()终止线程执行。

2.HanlderThread的原理

下面我们通过源码来分析一下HandlerThread:

public class HandlerThread extends Thread {    int mPriority;    int mTid = -1;    Looper mLooper;    public HandlerThread(String name) {        super(name);        mPriority = Process.THREAD_PRIORITY_DEFAULT;    }    public HandlerThread(String name, int priority) {        super(name);        mPriority = priority;    }    protected void onLooperPrepared() {    }    @Override    public void run() {        mTid = Process.myTid();        Looper.prepare();        synchronized (this) {            mLooper = Looper.myLooper();            notifyAll();    //唤醒其他线程的等待锁,这边是为了唤醒getLooper()方法中的等待锁        }        Process.setThreadPriority(mPriority);        onLooperPrepared();        Looper.loop();        mTid = -1;    }            public Looper getLooper() {        if (!isAlive()) {            return null;        }        // 线程开始,该方法会一直等待Looper对象创建完成才会执行,                       synchronized (this) {            while (isAlive() && mLooper == null) {                try {                    wait();                } catch (InterruptedException e) {                }            }        }        return mLooper;    }        public boolean quit() {        Looper looper = getLooper();        if (looper != null) {            looper.quit();            return true;        }        return false;    }        public boolean quitSafely() {        Looper looper = getLooper();        if (looper != null) {            looper.quitSafely();            return true;        }        return false;    }        public int getThreadId() {        return mTid;    }}

HandlerThread源码实现还是挺清楚的,首先我们看一下它的run()方法,可以发现该方法中调用Looper.myLooper()创建了一个Looper对象mLooper,并把该对象放到线程变量sThreadLocal中,然后通过调用Looper.loop()开启消息循环,Looper.loop()方法会不断循环从MessageQueue中取出消息处理消息,没有消息是则会阻塞。getLooper()方法是获取线程中的Looper对象,可以用来初始化Handler对象。
quit()quitSafely()的区别在于,quit()会清空所有消息(无论延时或非延时),quitSafely()只清空延时消息,无论是调用了quit()方法还是quitSafely()方法,Looper就不再接收新的消息。即在调用了Looperquit()quitSafely()方法之后,消息循环就终结了,这时候再通过Handler调用sendMessagepost等方法发送消息时均返回false,线程也就结束了

本人技术有限,欢迎指正,谢谢!

更多相关文章

  1. Android拍照流程
  2. Android与H5交互,向H5注入APP账号密码免登录等。
  3. 安卓笔记-视频版(还没学完)
  4. 如何让 android 完全退出
  5. android Activity 之 startActivityForResult 的使用
  6. Android(安卓)ActivityThread(主线程或UI线程)简介
  7. 安卓开发之 在应用中使用数据库
  8. Android(安卓)VOIP拨打电话机制分析
  9. Android中调用Paint的measureText()方法取得字符串显示的宽度值

随机推荐

  1. 4类危险的密码设置盲区,一起学习不要踩雷
  2. 数据保护即服务如何为组织业务提供帮助
  3. 如何将网页保存成mhtml格式
  4. SD卡插上一体机时显示文件或目录损坏且无
  5. 如何应对医疗行业的数据安全风险?
  6. 【知识点整理】NOLOGGING、APPEND、ARCHI
  7. 一个可悲的现实情况:中小型企业的规模无法
  8. CPU缓存L1/L2/L3工作原理
  9. sql 注入
  10. 【海量数据学院】DBA的学习方法论系列—