谈谈Android中的HandlerThread

一、简介

在详细讲解这篇文章之前,应该有部分的Android初级开发者并没用使用过HandlerThread,最常使用的消息传递机制应该离不开Handler,那么Handler跟HandlerThread有什么不同呢,好处又在哪里?

名詞解释
Handler在android中负责发送和处理消息,通过它可以实现其他支线线程与主线程之间的消息通讯
Thread进程中执行运算的最小单位,亦即执行处理机调度的基本单位
HandlerThread一个继承自Thread的类HandlerThread,Android中没有对Java中的Thread进行任何封装,而是提供了一个继承自Thread的类HandlerThread类,这个类对Java的Thread做了很多便利的封装

二、作用

HandlerThread是Thread的子类,HandlerThread本身就是一个线程,可以实现工作线程和主线程之间的通信,只是这个线程内部有一个Looper,而这个Looper有一个消息队列MessageQue,它通过不断的用Looper去检查MessageQue然后取出消息交给Handler处理,UI主线程本身亦是如此,HandlerThread可以分担MainLooper的工作量,降低了主线程的压力,使主界面更流畅。

三、优点

  • HandlerThread本质上是通过继承Thread类和封装Handler类的使用,从而使得创建新线程和与其他线程进行通信变得更加方便易用。
  • 降低主线程的压力,使主界面更流畅。
  • HandlerThread拥有自己的消息队列,它不会干扰或阻塞UI线程。

四、具体实现

public class MainActivity extends AppCompatActivity {

    Handler mainHandler,workHandler;
    HandlerThread mHandlerThread;
    TextView tv_content;
    Button button1,button2,button3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 显示文本
        tv_content= (TextView) findViewById(R.id.text1);

        // 创建与主线程关联的Handler
        mainHandler = new Handler();

        /**
          * 步骤1:创建HandlerThread实例对象
          * name: 线程名
          * priorit: 线程优先级
          */
        mHandlerThread = new HandlerThread("handlerThread",Process.THREAD_PRIORITY_BACKGROUND);
        /**
         * 步骤2:启动线程
         */
        mHandlerThread.start();

        /**
         * 步骤3:创建工作线程Handler,复写handleMessage()
         */
        workHandler = new Handler(mHandlerThread.getLooper()){
            @Override
            // 消息处理的操作
            public void handleMessage(Message msg)
            {
                switch(msg.what){
                    // 消息1
                    case 1:
                        try {
                            //延时操作
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        // 通过主线程Handler.post方法进行在主线程的UI更新操作
                        mainHandler.post(new Runnable() {
                            @Override
                            public void run () {
                                tv_content.setText("鱼王");
                            }
                        });
                        break;

                    // 消息2
                    case 2:
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        mainHandler.post(new Runnable() {
                            @Override
                            public void run () {
                                tv_content.setText("海王");
                            }
                        });
                        break;
                    default:
                        break;
                }
            }
        };

        /**
         * 步骤4:使用工作线程Handler向工作线程的消息队列发送消息
         * 在工作线程中,当消息循环时取出对应消息 & 在工作线程执行相关操作
         */
        // 点击Button1
        button1 = (Button) findViewById(R.id.button1);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 通过sendMessage()发送
                Message msg = Message.obtain();
                //消息的标识
                msg.what = 1; 
                // 消息的存放
                msg.obj = "111"; 
                workHandler.sendMessage(msg);
            }
        });

        // 点击Button2
        button2 = (Button) findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // 通过sendMessage()发送
                Message msg = Message.obtain();
                //消息的标识
                msg.what = 2; 
                // 消息的存放
                msg.obj = "2222"; 
                // b. 通过Handler发送消息到其绑定的消息队列
                workHandler.sendMessage(msg);
            }
        });

        // 点击Button3
        button3 = (Button) findViewById(R.id.button3);
        button3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //结束线程,即停止线程的消息循环
                mHandlerThread.quit();
            }
        });

    }
    
}

当我们调用Looper的quit方法时,实际上执行了MessageQueue中的removeAllMessagesLocked方法,该方法的作用是把MessageQueue消息池中所有的消息全部清空,无论是延迟消息(延迟消息是指通过sendMessageDelayed或通过postDelayed等方法发送的需要延迟执行的消息)还是非延迟消息。

总结

归根到底,HandlerThread可以分担MainLooper的工作量,降低了主线程的压力,使主界面更流畅,但是有是有引用HandlerThread的时候可能会引发内存泄漏,即:在Handler消息队列还有未处理的消息 / 正在处理消息时,此时若需销毁外部类MainActivity,但由于上述引用关系,垃圾回收器(GC)无法回收MainActivity,从而造成内存泄漏,下一篇博文会针对内存泄漏展开详细解说。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值