安卓开发面试题(9/30)HandlerThread全解析

牛客高级系列专栏:

安卓(安卓系统开发也要掌握)


嵌入式


本人是2020年毕业于广东工业大学研究生:许乔丹,有国内大厂CVTE和世界500强企业安卓开发经验,该专栏整理本人对常见安卓高频开发面试题的理解;

网上安卓资料千千万,笔者将继续维护专栏,一杯奶茶价格不止提供答案解析,承诺提供专栏内容免费技术答疑,直接咨询即可。助您提高安卓面试准备效率,为您面试保驾护航!

正文开始⬇

Handler异步消息处理机制是安卓面试的最常见内容之一,面试完问完Handler后可能来一句:“你了解HandlerThread”吗?此时如果能说上几句,一定可以给自己加分。面试官可能会问:

  1. HandlerThread是什么?⭐⭐⭐⭐⭐
  2. HandlerThread原理和使用场景?⭐⭐⭐⭐

看完以下的解析,一定可以让面试官眼前一亮。

目录

  • 1、HandlerThread是什么?
  • 2、HandlerThread怎么使用
  • 3、源码分析
  • 4、总结

1、HandlerThread是什么?

在安卓开发中,如果需要执行耗时操作,则可以开启子线程来完成,然而手动创建销毁线程又麻烦又消耗系统性能,因此可以使用线程池来完成。如果还需要在线程中使用Handler异步消息机制,或者需要实现子线程和子线程之间的通讯(Handler是主线程和子线程之间的通讯),那么就可以用HandlerThreaad

HandlerThread是Google封装好的一个类,它的内部有自己的Looper对象,可以进行Loop轮询,用于执行多个耗时操作,而不需要多次开启线程,本质是使用Handler和Looper实现的。

2、HandlerThread怎么使用

如果我们需要使用HandlerThread来读取一个大文件的内容,可以这么写:

public class Xuruictivity extends AppCompatActivity {
    private static final int MSG_READ_INFO = 100;
    Handler mMainHandler = new Handler();
    private Handler mThreadHandler;
    private HandlerThread mHandlerThread;
    private boolean isFinish = false; 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_xurui);
        initHandlerThread(); //1
        startHandlerThread(); 
    }

    private void initHandlerThread() {
        mHandlerThread = new HandlerThread("Xurui"); //2
        mHandlerThread.start(); //3 
        mThreadHandler = new Handler(mHandlerThread.getLooper()) { //4
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MSG_READ_INFO: {
                        readFileInfo();
                        // 如果没有读完,则继续
                        if (!isFinish) {
                            mThreadHandler.sendEmptyMessage(MSG_READ_INFO);
                        }
                    }
                    break;
                    default:
                        break;
                }
                
            }
        };
    }

    /**
     * 模拟读取文件
     */
    private void readFileInfo() {
        try {
            //模拟耗时
            Thread.sleep(1200);
            mMainHandler.post(new Runnable() {
                @Override
                public void run() {
                    // 读取大文件内容
                }
            });
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    private void startHandlerThread() {
       mThreadHandler.sendEmptyMessage(MSG_READ_INFO);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mThreadHandler.removeMessages(MSG_READ_INFO); //5
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandlerThread.quit();//6
        mMainHandler.removeCallbacksAndMessages(null); //7
    }
}

使用mHandlerThread的looper创建的mThreadHandler,对应注释4,里面的handleMessage是可以进行耗时操作的,因为它是执行在mHandlerThread所在的子线程。因此其优点是不会阻塞主线程,但是多任务时也需要有序执行,导致执行效率低。因此HandlerThread比较适合耗时不且不会产生较大的阻塞,比如读取文件,操作数据库等,至于网络IO操作这种可能有较大阻塞等,HandlerThread并不适合。

上面代码最关键的步骤都在注释1的函数里。我们来看看HandlerThread的使用方法:

  1. 创建HandlerThread实例:对应注释2,其中“xurui”是子线程的名字,可以随意取;
  2. 执行start函数来启动HandlerThread线程:对应注释3;
  3. 将HandlerThread和Handler绑定:对应注释4;
  4. 然后执行startHandlerThread()就行了,最后记得退出HandlerThread,对应注释6。

为何是这样的步骤,那就进入激动人心的源码分析吧!

3、源码分析

HandlerThread的源码仅仅100+行,因此直接copy完整的源码,不做任何删减(下面源码是android9.0.0的源码)。

public class HandlerThread extends Thread {
     int mPriority;
     int mTid = -1;
     Looper mLooper;
     private @Nullable Handler mHandler;

       public HandlerThread(String name) { //1
         super(name);
         mPriority = Process.THREAD_PRIORITY_DEFAULT;
     }

       /**
      * Constructs a HandlerThread.
      * @param name
      * @param priority The priority to run the thread at. The value supplied must be from
      * {@link android.os.Process} and not from java.lang.Thread.
      */
     public HandlerThread(String name, int priority) { //2
         super(name);
         mPriority = priority;
     }

       /**
      * Call back method that can be explicitly overridden if needed to execute some
      * setup befo

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

Android高频面试题全解析 文章被收录于专栏

#提供免费售后答疑!!花一杯奶茶的钱获得安卓面试答疑服务,稳赚不赔# Android发展已经很多年,安卓资料网上千千万,本专栏免费提供专栏内容技术答疑!!私聊当天必回。在阅读过程或者其他安卓学习过程有疑问,都非常欢迎私聊交流。

全部评论

相关推荐

12-14 22:54
武汉大学 Java
点赞 评论 收藏
分享
12-05 18:09
已编辑
广东药科大学 后端工程师
点赞 评论 收藏
分享
评论
12
12
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务