您好,登錄后才能下訂單哦!
一、HandlerThread的含義
HandlerThread能夠新建擁有Looper的線程。這個Looper能夠用來新建其他的Handler。(線程中的Looper)需要注意的是,新建的時候需要被回調(diào)。
二、HandlerThread的用法
一般情況下,我們會經(jīng)常用Handler在子線程中更新UI線程,那是因?yàn)樵谥骶€程中有Looper循環(huán),而HandlerThread新建擁有Looper的子線程又有什么用呢?
必然是執(zhí)行耗時操作。舉個例子,數(shù)據(jù)實(shí)時更新,我們每10秒需要切換一下顯示的數(shù)據(jù),如果我們將這種長時間的反復(fù)調(diào)用操作放到UI線程中,雖說可以執(zhí)行,但是這樣的操作多了之后,很容易會讓UI線程卡頓甚至崩潰。
于是,就必須在子線程中調(diào)用這些了。
HandlerThread繼承自Thread,一般適應(yīng)的場景,便是集Thread和Handler之所長,適用于會長時間在后臺運(yùn)行,并且間隔時間內(nèi)(或適當(dāng)情況下)會調(diào)用的情況,比如上面所說的實(shí)時更新。
三、實(shí)現(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()中的邏輯都是在子線程中運(yùn)行的。
接下來就是兩個關(guān)鍵的方法,run()和getLooper():
run()中可以看到是很簡單的創(chuàng)建Looper以及讓Looper工作的邏輯。
run()里面當(dāng)mLooper創(chuàng)建完成后有個notifyAll(),getLooper()中有個wait(),這有什么用呢?因?yàn)榈膍Looper在一個線程中執(zhí)行創(chuàng)建,而我們的handler是在UI線程中調(diào)用getLooper()初始化的。
也就是說,我們必須等到mLooper創(chuàng)建完成,才能正確的返回。getLooper();wait(),notify()就是為了解決這兩個線程的同步問題。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。