Android原始碼解析Handler系列第(四)篇 --- 打破Handler那些困惑事兒
Handler這個總共有4篇,這是最後一篇,前面三篇部落格,我們從原始碼的層面將Handler訊息機制梳理了一遍,現在回頭再看當時作為小白使用Hander所遇到的一些問題,顯然,這些問題基本都可以做一個解釋了。
Android原始碼解析Handler系列第(一)篇 --- Message全域性池
Android原始碼解析Handler系列第(二)篇 --- ThreadLocal詳解
Android原始碼解析Handler系列第(三)篇 --- 深入瞭解Android的訊息機制
-1、為什麼不能在子執行緒執行緒中更新UI?
這個答案可以在ViewRootImpl中找到,ViewRootImpl對UI的操作做了驗證,如果不是主執行緒,就會丟擲CalledFromWrongThreadException。
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}
進一步思考,為什麼ViewRootImpl要做checkThread的操作呢,因為多執行緒併發訪問UI是不安全的,但是如果用同步鎖不僅會降低效能,也會使邏輯變得複雜,所以就採用單執行緒模型,這活交給了主執行緒來幹!
-2 、下面這段程式碼為什麼會報錯?
new Thread(new Runnable() {
@Override
public void run() {
Handler handler=new Handler();
}
}).start();
建立Handler的時候,就會呼叫Looper.myLooper()去獲取Looper物件。myLooper方法中會通過sThreadLocal.get()獲取返回,沒有獲取到就丟擲RuntimeException。
public Handler(Callback callback, boolean async) {
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
每一個執行緒都需要有自己的Looper,主執行緒在ActivityThread的main方法中預設給我們建立了Looper。對於子執行緒需要我們自己建立。解決方式如下:
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Handler handler=new Handler();
}
}).start();
這樣子執行緒就有了自己的Looper,也有了自己的MessageQueue。但是這樣還是有問題的,當你用handler傳送一個訊息,並不能收到訊息的回撥,因為你沒有啟動訊息迴圈,只有呼叫Looper.loop()之後,Looper才能不斷的從訊息佇列中取出訊息交給Handler分發處理。即最終的解決方案是這樣的。
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Handler handler=new Handler();
Looper.loop()
}
}).start();
-3、使用Handler為什麼會容易記憶體洩露?
下面是一段“常規”寫法
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
mImageView.setImageBitmap(mBitmap);
}
}
因為內部類會有一個指向外部類的引用(這個Handler又持有Activity的引用,就導致該Activity無法被回收)。垃圾回收機制中約定,當記憶體中的一個物件的引用計數為0時,將會被回收Handler作為Android上的非同步訊息處理機制(好吧,我大多用來進行worker thread與UI執行緒同步),它的工作是需要Looper和MessageQueue配合的。簡單的說,要維護一個迴圈體(Looper)處理訊息佇列(MessageQueue)。每迴圈一次就從MessageQueue中取出一個Message,然後回撥相應的訊息處理函式。如果,迴圈體中有訊息未處理(Message排隊中),那麼Handler會一直存在,那麼Handler的外部類(通常是Activity)的引用計數一直不會是0,所以那個外部類就不能被垃圾回收。很多人會遇到activity的onDestroy方法一直不執行就是這個原因。
解決方案
static class MyHandler extends Handler {
WeakReference<Activity > mActivityReference;
MyHandler(Activity activity) {
mActivityReference= new WeakReference<Activity>(activity);
}
@Override
public void handleMessage(Message msg) {
final Activity activity = mActivityReference.get();
if (activity != null) {
mImageView.setImageBitmap(mBitmap);
}
}
}
Please accept mybest wishes for your happiness and success
參考連結:http://blog.csdn.net/lincyang/article/details/46875157
原文連結:http://www.jianshu.com/p/338cce832cc9
著作權歸作者所有,轉載請聯絡作者獲得授權,並標註“簡書作者”。
相關文章
- 原始碼篇:Handler那些事(萬字長文)原始碼
- Handler系列原始碼解析原始碼
- Android原始碼解析Handler系列第(五)篇 ---HandlerThread你用過嗎?Android原始碼thread
- Android Handler 原始碼解析Android原始碼
- Android 8.1 Handler 原始碼解析Android原始碼
- Android 9.0 原始碼_機制篇 -- 全面解析 HandlerAndroid原始碼
- Handler原始碼解析原始碼
- Handler全家桶之 —— Handler 原始碼解析原始碼
- Android Handler 原始碼探索Android原始碼
- Android——Handler原始碼分析Android原始碼
- 【Android原始碼】Handler 機制原始碼分析Android原始碼
- Android原始碼學習之handlerAndroid原始碼
- Android開發Handler原始碼分析Android原始碼
- Handler原始碼分析原始碼
- Handler原始碼剖析原始碼
- 手把手帶你解析Handler原始碼原始碼
- Handler解析
- Android 原始碼分析(二)handler 機制Android原始碼
- Android Handler機制使用,原始碼分析Android原始碼
- 深入原始碼解析Android中的Handler,Message,MessageQueue,Looper原始碼AndroidOOP
- Handler訊息機制完全解析Handler解析
- Handler原始碼解讀原始碼
- Netty原始碼解析4-Handler綜述Netty原始碼
- 原始碼深度解析 Handler 機制及應用原始碼
- Android 進階 ———— Handler系列之建立子執行緒HandlerAndroid執行緒
- [Handler]android-Handler解釋Android
- Android多執行緒之Handler、Looper與MessageQueue原始碼解析Android執行緒OOP原始碼
- Handler訊息處理機制原始碼解析 上原始碼
- 從原始碼去理解Handler原始碼
- Android--Handler機制及原始碼詳解Android原始碼
- Android Handler訊息機制原始碼解讀Android原始碼
- Handler機制解析
- 從原始碼角度來讀Handler原始碼
- Android的Handler訊息機制 解析Android
- Android IntentService完全解析 當Service遇到HandlerAndroidIntent
- [HTTP 系列] 第 2 篇 —— HTTP 協議那些事HTTP協議
- Android Handler機制之Handler 、MessageQueue 、LooperAndroidOOP
- Android中HandlerAndroid