Android 進階 ———— Handler系列之建立子執行緒Handler
上一篇我介紹了Handler機制的工作原理,預設情況下,ActivityThread類為我們建立的了主執行緒的Looper和訊息佇列,所以當你建立Handler之後傳送訊息的時候,訊息的輪訓和handle都是在ui執行緒進行的。這種情況屬於子執行緒給主執行緒發訊息,通知主執行緒更新ui…等,那麼反過來,怎麼才能讓主執行緒給子執行緒發訊息,通知子執行緒做一些耗時邏輯??
之前的學習我們知道,Android的訊息機制遵循三個步驟:
1 建立當前執行緒的Looper
2 建立當前執行緒的Handler
3 呼叫當前執行緒Looper物件的loop方法
看過之前文章的朋友會注意到,本篇我特意強調了“當前執行緒”。是的之前我們學習的很多都是Android未我們做好了的,譬如:建立主執行緒的Looper、主執行緒的訊息佇列…就連我們使用的handler也是主執行緒的。那麼如果我想建立非主執行緒的Handler並且傳送訊息、處理訊息,這一系列的操作我們應該怎麼辦那???不怎麼辦、涼拌~~~什麼意思???依葫蘆畫瓢,依然遵循上面的三步走,直接上程式碼!!!!
public class ChildThreadHandlerActivity extends Activity {
private MyThread childThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler);
childThread = new MyThread();
childThread.start();
Handler childHandler = new Handler(childThread.childLooper){//這樣之後,childHandler和childLooper就關聯起來了。
public void handleMessage(Message msg) {
};
};
}
private class MyThread extends Thread{
public Looper childLooper;
@Override
public void run() {
Looper.prepare();//建立與當前執行緒相關的Looper
childLooper = Looper.myLooper();//獲取當前執行緒的Looper物件
Looper.loop();//呼叫此方法,訊息才會迴圈處理
}
}
}
程式碼如上,我們依然循序Android的三步走戰略,完成了子執行緒Handler的建立,難道這樣建立完了,就可以發訊息了麼?發的訊息在什麼執行緒處理?一系列的問題,怎麼辦?看程式碼!!!執行上述程式碼,我們發現一個問題,就是此程式碼一會崩潰、一會不崩潰,通過檢視日誌我們看到崩潰的原因是空指標。誰為空???查到是我們的Looper物件,怎麼會那?我不是在子執行緒的run方法中初始化Looper物件了麼?話是沒錯,但是你要知道,當你statr子執行緒的時候,雖然子執行緒的run方法得到執行,但是主執行緒中程式碼依然會向下執行,造成空指標的原因是當我們new Handler(childThread.childLooper)的時候,run方法中的Looper物件還沒初始化。當然這種情況是隨機的,所以造成偶現的崩潰。
那怎麼辦?難道我們不能建立子執行緒Handler ???No!!!No!!!No!!!,你能想到的Android早就為我們實現好了,HandlerThread類就是解決這個問題的關鍵所在,看程式碼!!!
public class HandlerThreadActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler);
TextView textView = (TextView) findViewById(R.id.tv);
textView.setText("HandlerThreadActivity.class");
HandlerThread handlerThread = new HandlerThread("HandlerThread");
handlerThread.start();
Handler mHandler = new Handler(handlerThread.getLooper()){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.d("HandlerThreadActivity.class","uiThread2------"+Thread.currentThread());//子執行緒
}
};
Log.d("HandlerThreadActivity.class","uiThread1------"+Thread.currentThread());//主執行緒
mHandler.sendEmptyMessage(1);
}
}
建立HandlerThread物件的時候,有個引數,是指定執行緒名字的。上面的程式碼不管執行多少次都不會奔潰!!!並且這種方法建立的handler的handleMessage方法執行在子執行緒中。所以我們可以在這裡處理一些耗時的邏輯。到此我們完成了主執行緒給子執行緒發通知,在子執行緒做耗時邏輯的操作。
下面我們去看看原始碼,看看為什麼使用HandlerThread就可以避免空指標那?
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;
}
HandlerThread類的getLooper方法如上,我們看到當我們獲取當前執行緒Looper物件的時候,會先判斷當前執行緒是否存活,然後還要判斷Looper物件是否為空,都滿足之後才會返回給我Looper物件,否則處於等待狀態!!既然有等待,那就有喚醒的時候,在那裡那???我們發現HandlerThread的run方法中,有如下程式碼:
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
說明了什麼那???HandlerThread類start的時候,Looper物件就初始化了,並喚醒之前等待的。所以HandlerThread很好的避免了之前空指標的產生。所以以後要想建立非主執行緒的Handler時,我們用HandlerThread類提供的Looper物件即可。
相關文章
- 子執行緒中建立Handler可以嗎?(上)執行緒
- Handler怎麼進行執行緒通訊?Handler原理解讀執行緒
- 大話Android多執行緒(三) 執行緒間的通訊機制之HandlerAndroid執行緒
- Android多執行緒之Handler、Looper與MessageQueue原始碼解析Android執行緒OOP原始碼
- Android多執行緒基礎 解析Handler機制Android執行緒
- Android進階知識:Handler相關Android
- Android之HandlerAndroid
- Android程式框架:執行緒通訊的橋樑HandlerAndroid框架執行緒
- Android Handler機制之Handler 、MessageQueue 、LooperAndroidOOP
- Android進階;Handler訊息機制詳解Android
- new Handler().postDelayed(new Runnable())是否執行在主執行緒?執行緒
- Android執行緒間訊息機制-Handler原始碼分析(FrameWork)Android執行緒原始碼Framework
- [Handler]android-Handler解釋Android
- Android 基礎之 HandlerAndroid
- Android開發之HandlerAndroid
- Android 多執行緒:你的 Handler 記憶體洩露 了嗎?Android執行緒記憶體洩露
- Handler全家桶之 —— Handler 原始碼解析原始碼
- Android 高階面試-1:Handler 相關Android面試
- Android原始碼解析Handler系列第(四)篇 --- 打破Handler那些困惑事兒Android原始碼
- Android高階進階之路【四】一文讀懂 Handler 機制Android
- Java多執行緒之進階篇Java執行緒
- Android進階:六、在子執行緒中直接使用 Toast 及其原理Android執行緒AST
- Android中HandlerAndroid
- Android Handler原理Android
- Android原始碼學習之handlerAndroid原始碼
- Android Handler機制之ThreadLocalAndroidthread
- android非同步圖片載入三之handler+執行緒池+訊息佇列模式+快取Android非同步執行緒佇列模式快取
- Handler系列原始碼解析原始碼
- 多執行緒系列之 執行緒安全執行緒
- Android Handler機制之總目錄Android
- Android學習-HandlerAndroid
- Android中的handlerAndroid
- netty系列之:Event、Handler和PipelineNetty
- Handler訊息機制及handler原理(Handler,Looper,MessageQueue),自定義HandlerOOP
- android 主執行緒和子執行緒之間的訊息傳遞Android執行緒
- 進階Java多執行緒Java執行緒
- Java執行緒池進階Java執行緒
- java多執行緒系列之執行緒池Java執行緒