HandlerThread的使用以及原理
HandlerThread
如果已經理解Handler,Loop,MessageQueue的工作原理看此篇文章會非常簡單,若沒有了解的讀者,可以看下面的文章:
Handler類和Handler,Loop,MessageQueue的工作原理
首先我們先看一下官方的描述:
Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.
大致意思是HandlerThread能夠新建擁有Looper的執行緒。這個Looper能夠用來新建其他的Handler。(執行緒中的Looper)需要注意的是,新建的時候需要被回撥。
用法
一般情況下,我們會經常用Handler在子執行緒中更新UI執行緒,那是因為在主執行緒中有Looper迴圈,而HandlerThread新建擁有Looper的子執行緒又有什麼用呢?
必然是執行耗時操作。舉個例子,資料實時更新,我們每10秒需要切換一下顯示的資料,如果我們將這種長時間的反覆呼叫操作放到UI執行緒中,雖說可以執行,但是這樣的操作多了之後,很容易會讓UI執行緒卡頓甚至崩潰。
於是,就必須在子執行緒中呼叫這些了。
HandlerThread繼承自Thread,一般適應的場景,便是集Thread和Handler之所長,適用於會長時間在後臺執行,並且間隔時間內(或適當情況下)會呼叫的情況,比如上面所說的實時更新。
其實使用HandlerThread的效果和使用Thread+Handler差不多。不過後者對開發者的要求更高。
效果
功能:每2秒更新一下UI。
主要程式碼:
package com.example.double2.handlerthreadtest;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView tvMain;
private HandlerThread mHandlerThread;
//子執行緒中的handler
private Handler mThreadHandler;
//UI執行緒中的handler
private Handler mMainHandler = new Handler();
//以防退出介面後Handler還在執行
private boolean isUpdateInfo;
//用以表示該handler的常熟
private static final int MSG_UPDATE_INFO = 0x110;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvMain = (TextView) findViewById(R.id.tv_main);
initThread();
}
private void initThread()
{
mHandlerThread = new HandlerThread("check-message-coming");
mHandlerThread.start();
mThreadHandler = new Handler(mHandlerThread.getLooper())
{
@Override
public void handleMessage(Message msg)
{
update();//模擬資料更新
if (isUpdateInfo)
mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO);
}
};
}
private void update()
{
try
{
//模擬耗時
Thread.sleep(2000);
mMainHandler.post(new Runnable()
{
@Override
public void run()
{
String result = "每隔2秒更新一下資料:";
result += Math.random();
tvMain.setText(result);
}
});
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
@Override
protected void onResume()
{
super.onResume();
//開始查詢
isUpdateInfo = true;
mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO);
}
@Override
protected void onPause()
{
super.onPause();
//停止查詢
//以防退出介面後Handler還在執行
isUpdateInfo = false;
mThreadHandler.removeMessages(MSG_UPDATE_INFO);
}
@Override
protected void onDestroy()
{
super.onDestroy();
//釋放資源
mHandlerThread.quit();
}
}
原理:
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();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
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繼承自Thread,因此在run()中的邏輯都是在子執行緒中執行的。
接下來就是兩個關鍵的方法,run()和getLooper():
run()中可以看到是很簡單的建立Looper以及讓Looper工作的邏輯。
run()裡面當mLooper建立完成後有個notifyAll(),getLooper()中有個wait(),這有什麼用呢?因為的mLooper在一個執行緒中執行建立,而我們的handler是在UI執行緒中呼叫getLooper()初始化的。
也就是說,我們必須等到mLooper建立完成,才能正確的返回。getLooper();wait(),notify()就是為了解決這兩個執行緒的同步問題。
相關文章
- 理解 HandlerThread 原理thread
- IntentService 和 HandlerThread 的原理Intentthread
- HandlerThread解析以及相關問題分析thread
- vip原理以及使用
- 看完這篇。再也不怕被問 HandlerThread 的原理thread
- Android HandlerThread使用總結Androidthread
- React-redux的原理以及簡單使用ReactRedux
- MySQL 5.6 GTID 原理以及使用MySql
- Android中HandlerThread的使用及原始碼解析Androidthread原始碼
- 淺析地面投影的使用原理以及優點
- CyclicBarrier、CountDownLatch以及Semaphore使用及其原理分析CountDownLatch
- Threadlocal的使用以及實現原理總結thread
- Picasso原始碼分析(三):快照功能實現和HandlerThread的使用原始碼thread
- HandlerThread原始碼解析thread原始碼
- Android 中的 HandlerThread 詳解Androidthread
- 交換機的概念以及工作原理
- Mysql的複製原理以及流程MySql
- GPU的介紹 以及原理的分析GPU
- iOS底層-KVC使用實踐以及實現原理iOS
- 面試官:同學,說說 Applink 的使用以及原理面試APP
- 終止Android中HandlerThread的方法Androidthread
- 紅黑樹的原理以及實現
- Synchronized的實現原理以及優化synchronized優化
- 堆的原理以及實現O(lgn)
- 關於Servlet的原理以及常用類Servlet
- Go的執行原理以及Go的命令Go
- Android Jetpack元件 - ViewModel,LiveData使用以及原理AndroidJetpack元件ViewLiveData
- framework7的改進,以及與vue組合使用遇到的問題以及解決方法 (附vue的原理)FrameworkVue
- 知道Handler,那你知道HandlerThread嗎?thread
- HandlerThread和IntentService原始碼解析threadIntent原始碼
- Android 進階之HandlerThread 使用場景及原始碼解析Androidthread原始碼
- JavaScript 中 this 的工作原理以及注意事項JavaScript
- JavaScript中this的工作原理以及注意事項JavaScript
- 節流原理以及實現
- MySQL 索引原理以及優化MySql索引優化
- Ajax原理以及優缺點
- Stream常用操作以及原理探索
- 【MySQL】order by 原理以及優化MySql優化