Android HandlerThread案例詳解
HandlerThread 顧名思義就是一種可以使用 Handler 的 Thread。日常開(kāi)發(fā)中我們經(jīng)常會(huì)通過(guò)創(chuàng)建一個(gè) Thread 去執(zhí)行任務(wù),有多個(gè)任務(wù)就多創(chuàng)建幾個(gè)線程實(shí)現(xiàn),這時(shí)候可能出現(xiàn)線程同步的問(wèn)題。不過(guò)有時(shí)候我們并不需要很強(qiáng)的并發(fā)性,只需保證按照順序地執(zhí)行各個(gè)任務(wù)即可,有什么好辦法實(shí)現(xiàn)呢?第一反應(yīng)想到的可能是通過(guò) Executors.newSingleThreadExecutor() 方法來(lái)創(chuàng)建一個(gè) SingleThreadExecutor,來(lái)統(tǒng)一所有的任務(wù)到一個(gè)線程中,然后按順序執(zhí)行。其實(shí),除了這個(gè)方法之外,HandlerThread 也可以實(shí)現(xiàn)。
簡(jiǎn)單使用
首先創(chuàng)建一個(gè) HandlerThreadActivity
public class HandlerThreadActivity extends BaseActivity { private static final String TAG = "HandlerThreadActivity"; private Button mStartBtn; private Handler mHandler; private HandlerThread mHandlerThread; @Override protected 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() { @Override public void onClick(View v) { mHandler.post(new Runnable() { @Override public void run() { Log.d(TAG, Thread.currentThread().getId() + " " + String.valueOf((Looper.myLooper() == Looper.getMainLooper())) + " 任務(wù):" + this.hashCode()); SystemClock.sleep(3000); } }); } }); } @Override protected void onDestroy() { super.onDestroy(); mHandlerThread.quit(); } }
快速三擊按鈕,打印日志如下:
可以發(fā)現(xiàn),三次不同的任務(wù)按開(kāi)始的順序執(zhí)行,而且是運(yùn)行在子線程中,那到底是怎么實(shí)現(xiàn)的呢?
源碼解析
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() { } @Override public void run() { // 獲取線程 id mTid = Process.myTid(); //構(gòu)建一個(gè) Looper Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } //設(shè)置線程優(yōu)先級(jí) Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); // Looper 循環(huán) mTid = -1; } // 獲取當(dāng)前線程的 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 方法隱藏掉,無(wú)法調(diào)用 */ @NonNull public Handler getThreadHandler() { if (mHandler == null) { mHandler = new Handler(getLooper()); } return mHandler; } //線程退出方法,主要是調(diào)用 Looper.quit() 方法,不然一直在循環(huán) public boolean quit() { Looper looper = getLooper(); if (looper != null) { looper.quit(); return true; } return false; } //同上,不過(guò)這個(gè)方法會(huì)把消息隊(duì)列中的已有消息處理完才會(huì)安全地退出 public boolean quitSafely() { Looper looper = getLooper(); if (looper != null) { looper.quitSafely(); return true; } return false; } public int getThreadId() { return mTid; } }
通讀下來(lái),如果熟悉 Handler 原理的同學(xué)大概就明白 HandlerThread 的機(jī)制了:
- HandlerThread 運(yùn)行 start() 方法,回調(diào) run() 方法。
- 在 run() 方法中通過(guò) Looper.prepare() 來(lái)創(chuàng)建消息隊(duì)列,并通過(guò) Looper.looper() 方法來(lái)開(kāi)啟消息循環(huán)。
- 由于 Loop.loop() 是一個(gè)死循環(huán),導(dǎo)致 run() 也是無(wú)線循環(huán),因此當(dāng)我們不需要使用 HandlerThread 的時(shí)候,要調(diào)用它的 quit() 方法或者 quiteSafely() 方法。
到此這篇關(guān)于Android HandlerThread案例詳解的文章就介紹到這了,更多相關(guān)Android HandlerThread內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Kotlin協(xié)程Job生命周期結(jié)構(gòu)化并發(fā)詳解
這篇文章主要為大家介紹了Kotlin協(xié)程Job生命周期結(jié)構(gòu)化并發(fā)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12Android Insets相關(guān)知識(shí)總結(jié)
這篇文章主要介紹了Android Insets相關(guān)知識(shí)總結(jié),幫助大家更好的理解和學(xué)習(xí)使用Android,感興趣的朋友可以了解下2021-03-03大型項(xiàng)目里Flutter測(cè)試應(yīng)用實(shí)例集成測(cè)試深度使用詳解
這篇文章主要為大家介紹了大型項(xiàng)目里Flutter測(cè)試應(yīng)用實(shí)例集成測(cè)試深度使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12Android自定義SeekBar實(shí)現(xiàn)滑動(dòng)驗(yàn)證且不可點(diǎn)擊
這篇文章主要為大家詳細(xì)介紹了Android自定義SeekBar實(shí)現(xiàn)滑動(dòng)驗(yàn)證且不可點(diǎn)擊,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03Android 邊播邊緩存的實(shí)現(xiàn)(MP4 未加密m3u8)
這篇文章主要介紹了Android 邊播邊緩存的實(shí)現(xiàn)(MP4 未加密m3u8),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11Android Handler消息派發(fā)機(jī)制源碼分析
這篇文章主要為大家詳細(xì)分析了Android Handler消息派發(fā)機(jī)制源碼,感興趣的小伙伴們可以參考一下2016-07-07Android手勢(shì)操作示例(上/下/左/右的判斷)
這篇文章主要介紹了Android手勢(shì)操作方法,包含了針對(duì)上、下、左、右等方向的判斷,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06Android快速實(shí)現(xiàn)無(wú)預(yù)覽拍照功能
這篇文章主要為大家詳細(xì)介紹了Android快速實(shí)現(xiàn)無(wú)預(yù)覽拍照功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06