Android|Android HandlerThread案例详解
HandlerThread 顾名思义就是一种可以使用 Handler 的 Thread。日常开发中我们经常会通过创建一个 Thread 去执行任务,有多个任务就多创建几个线程实现,这时候可能出现线程同步的问题。不过有时候我们并不需要很强的并发性,只需保证按照顺序地执行各个任务即可,有什么好办法实现呢?第一反应想到的可能是通过 Executors.newSingleThreadExecutor() 方法来创建一个 SingleThreadExecutor,来统一所有的任务到一个线程中,然后按顺序执行。其实,除了这个方法之外,HandlerThread 也可以实现。
简单使用
首先创建一个 HandlerThreadActivity
public class HandlerThreadActivity extends BaseActivity {private static final String TAG = "HandlerThreadActivity"; private Button mStartBtn; private Handler mHandler; private HandlerThread mHandlerThread; @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); setContentView(R.layout.activity_handler_thread); mStartBtn = findViewById(R.id.start_btn); mHandlerThread = new HandlerThread("THREAD_NAME"); mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper()); mStartBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {mHandler.post(new Runnable() {@Overridepublic void run() {Log.d(TAG, Thread.currentThread().getId() + " " + String.valueOf((Looper.myLooper() == Looper.getMainLooper())) + " 任务:" + this.hashCode()); SystemClock.sleep(3000); }}); }}); }@Overrideprotected void onDestroy() {super.onDestroy(); mHandlerThread.quit(); }}
快速三击按钮,打印日志如下:
![Android|Android HandlerThread案例详解](https://img.it610.com/image/info11/86d2df7f557a41718520f88f4a4e5c75.jpg)
文章图片
【Android|Android HandlerThread案例详解】可以发现,三次不同的任务按开始的顺序执行,而且是运行在子线程中,那到底是怎么实现的呢?
源码解析
public class HandlerThread extends Thread {int mPriority; int mTid = -1; Looper mLooper; private @Nullable Handler mHandler; public HandlerThread(String name) {super(name); mPriority = Process.THREAD_PRIORITY_DEFAULT; }public HandlerThread(String name, int priority) {super(name); mPriority = priority; }protected void onLooperPrepared() {}@Overridepublic void run() {// 获取线程 idmTid = Process.myTid(); //构建一个 LooperLooper.prepare(); synchronized (this) {mLooper = Looper.myLooper(); notifyAll(); }//设置线程优先级Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); // Looper 循环mTid = -1; }// 获取当前线程的 Looper,public Looper getLooper() {if (!isAlive()) {return null; }synchronized (this) {while (isAlive() && mLooper == null) {try {wait(); } catch (InterruptedException e) {}}}return mLooper; }/*** @return a shared {@link Handler} associated with this thread* @hide 方法隐藏掉,无法调用*/@NonNullpublic Handler getThreadHandler() {if (mHandler == null) {mHandler = new Handler(getLooper()); }return mHandler; }//线程退出方法,主要是调用 Looper.quit() 方法,不然一直在循环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; }}
通读下来,如果熟悉 Handler 原理的同学大概就明白 HandlerThread 的机制了:
- HandlerThread 运行 start() 方法,回调 run() 方法。
- 在 run() 方法中通过 Looper.prepare() 来创建消息队列,并通过 Looper.looper() 方法来开启消息循环。
- 由于 Loop.loop() 是一个死循环,导致 run() 也是无线循环,因此当我们不需要使用 HandlerThread 的时候,要调用它的 quit() 方法或者 quiteSafely() 方法。
推荐阅读
- android第三方框架(五)ButterKnife
- Android中的AES加密-下
- 带有Hilt的Android上的依赖注入
- android|android studio中ndk的使用
- Android事件传递源码分析
- RxJava|RxJava 在Android项目中的使用(一)
- Android7.0|Android7.0 第三方应用无法访问私有库
- 深入理解|深入理解 Android 9.0 Crash 机制(二)
- android防止连续点击的简单实现(kotlin)
- Android|Android install 多个设备时指定设备