Android HandlerThread的使用及原理詳解
一、HandlerThread的含義
HandlerThread能夠新建擁有Looper的線程。這個Looper能夠用來新建其他的Handler。(線程中的Looper)需要注意的是,新建的時候需要被回調(diào)。
二、HandlerThread的用法
一般情況下,我們會經(jīng)常用Handler在子線程中更新UI線程,那是因為在主線程中有Looper循環(huán),而HandlerThread新建擁有Looper的子線程又有什么用呢?
必然是執(zhí)行耗時操作。舉個例子,數(shù)據(jù)實時更新,我們每10秒需要切換一下顯示的數(shù)據(jù),如果我們將這種長時間的反復(fù)調(diào)用操作放到UI線程中,雖說可以執(zhí)行,但是這樣的操作多了之后,很容易會讓UI線程卡頓甚至崩潰。
于是,就必須在子線程中調(diào)用這些了。
HandlerThread繼承自Thread,一般適應(yīng)的場景,便是集Thread和Handler之所長,適用于會長時間在后臺運行,并且間隔時間內(nèi)(或適當(dāng)情況下)會調(diào)用的情況,比如上面所說的實時更新。
三、實現(xiàn)每2秒更新一下UI
public class MainActivity extends AppCompatActivity {
private TextView tvMain;
private HandlerThread mHandlerThread;
//子線程中的handler
private Handler mThreadHandler;
//UI線程中的handler
private Handler mMainHandler = new Handler();
//以防退出界面后Handler還在執(zhí)行
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();//模擬數(shù)據(jù)更新
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秒更新一下數(shù)據(jù):";
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還在執(zhí)行
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()中的邏輯都是在子線程中運行的。
接下來就是兩個關(guān)鍵的方法,run()和getLooper():
run()中可以看到是很簡單的創(chuàng)建Looper以及讓Looper工作的邏輯。
run()里面當(dāng)mLooper創(chuàng)建完成后有個notifyAll(),getLooper()中有個wait(),這有什么用呢?因為的mLooper在一個線程中執(zhí)行創(chuàng)建,而我們的handler是在UI線程中調(diào)用getLooper()初始化的。
也就是說,我們必須等到mLooper創(chuàng)建完成,才能正確的返回。getLooper();wait(),notify()就是為了解決這兩個線程的同步問題。
相關(guān)文章
淺談 Android 7.0 多窗口分屏模式的實現(xiàn)
這篇文章主要介紹了淺談 Android 7.0 多窗口分屏模式的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
Android開發(fā)中l(wèi)ibs和jinLibs文件夾的作用詳解
這篇文章主要給大家介紹了關(guān)于Android開發(fā)中l(wèi)ibs和jinLibs文件夾的作用的相關(guān)資料,文中通過圖文及示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。2017-09-09
Android開發(fā)之ClipboardManager剪貼板功能示例
這篇文章主要介紹了Android開發(fā)之ClipboardManager剪貼板功能,結(jié)合簡單實例形式分析了Android使用ClipboardManager實現(xiàn)剪貼板功能的相關(guān)操作技巧,需要的朋友可以參考下2017-03-03
android viewpager實現(xiàn)豎屏滑動效果
這篇文章主要為大家詳細介紹了android viewpager實現(xiàn)豎屏滑動效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-07-07
Android程序開發(fā)之Listview下拉刷新上拉(滑動分頁)加載更多
這篇文章主要介紹了Android程序開發(fā)之Listview下拉刷新上拉(滑動分頁)加載更多的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-07-07
BroadcastReceiver動態(tài)注冊案例詳解
這篇文章主要為大家詳細介紹了BroadcastReceiver動態(tài)注冊案例,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-08-08
以一個著色游戲展開講解Android中區(qū)域圖像填色的方法
這篇文章主要介紹了Android中實現(xiàn)區(qū)域圖像顏色填充的方法,文中以一個著色游戲為例講解了邊界的填充等各種填色操作,需要的朋友可以參考下2016-02-02
Android MediaPlayer音頻播放器封裝示例淺析
Android提供了許多方法來控制播放的音頻/視頻文件和流。其中該方法是通過一類稱為MediaPlayer。Android是提供MediaPlayer類訪問內(nèi)置的媒體播放器的服務(wù),如播放音頻,視頻等為了使用MediaPlayer,我們要調(diào)用這個類的靜態(tài)create()方法2023-04-04

