內部Handler類引起記憶體洩露
原文地址:http://blog.chengyunfeng.com/?p=468
如果您在Activity中定義了一個內部Handler類,如下程式碼:
public class MainActivity extends Activity {
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
//TODO handle message...
}
};
@TargetApi(11)
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler.sendMessageDelayed(Message.obtain(), 60000);
//just finish this activity
finish();
}
}
Read more: http://blog.chengyunfeng.com/?p=468#ixzz445wT2Gpw
然後執行Android Lint工具會有一個記憶體洩露警告:
This Handler class should be static or leaks might occur (com.example.ta.MainActivity.1)
Issue: Ensures that Handler classes do not hold on to a reference to an outer class
Id: HandlerLeakIn Android, Handler classes should be static or leaks might occur. Messages enqueued on the application thread’s MessageQueue also retain their target Handler. If the Handler is an inner class, its outer class will be retained as well. To avoid leaking the outer class, declare the Handler as a static nested class with a WeakReference to its outer class.
原因是:
- 當Android應用啟動的時候,會先建立一個應用主執行緒的Looper物件,Looper實現了一個簡單的訊息佇列,一個一個的處理裡面的Message物件。主執行緒Looper物件在整個應用生命週期中存在。
- 當在主執行緒中初始化Handler時,該Handler和Looper的訊息佇列關聯。傳送到訊息佇列的Message會引用傳送該訊息的Handler物件,這樣系統可以呼叫 Handler#handleMessage(Message) 來分發處理該訊息。
- 在Java中,非靜態(匿名)內部類會引用外部類物件。而靜態內部類不會引用外部類物件。
- 如果外部類是Activity,則會引起Activity洩露 。
當Activity finish後,延時訊息會繼續存在主執行緒訊息佇列中1分鐘,然後處理訊息。而該訊息引用了Activity的Handler物件,然後這個Handler又引用了這個Activity。這些引用物件會保持到該訊息被處理完,這樣就導致該Activity物件無法被回收,從而導致了上面說的 Activity洩露。
要修改該問題,只需要按照Lint提示的那樣,把Handler類定義為靜態即可,然後通過WeakReference 來保持外部的Activity物件。
private Handler mHandler = new MyHandler(this);
private static class MyHandler extends Handler{
private final WeakReference<Activity> mActivity;
public MyHandler(Activity activity) {
mActivity = new WeakReference<Activity>(activity);
}
@Override
public void handleMessage(Message msg) {
System.out.println(msg);
if(mActivity.get() == null) {
return;
}
}
}
Read more: http://blog.chengyunfeng.com/?p=468#ixzz445wZB4mt
所以,當你在Activity中使用內部類的時候,需要時刻考慮您是否可以控制該內部類的生命週期,如果不可以,則最好定義為靜態內部類。
Read more: http://blog.chengyunfeng.com/?p=468#ixzz445vzsIoB
相關文章
- android Handler導致的記憶體洩露Android記憶體洩露
- 小題大做 | Handler記憶體洩露全面分析記憶體洩露
- Android中使用Handler造成記憶體洩露的分析和解決Android記憶體洩露
- SHBrowseForFolder 記憶體洩露記憶體洩露
- WebView引起的記憶體洩漏WebView記憶體
- 記憶體溢位和記憶體洩露記憶體溢位記憶體洩露
- Lowmemorykiller記憶體洩露分析記憶體洩露
- 使用 mtrace 分析 “記憶體洩露”記憶體洩露
- 實戰Go記憶體洩露Go記憶體洩露
- Android 記憶體洩露詳解Android記憶體洩露
- Handler記憶體洩漏分析及解決記憶體
- Android Handler機制之記憶體洩漏Android記憶體
- Handler的使用、記憶體洩漏和解決記憶體
- Linux記憶體洩露案例分析和記憶體管理分享Linux記憶體洩露
- ArkTS 的記憶體快照與記憶體洩露除錯記憶體洩露除錯
- nodejs爬蟲記憶體洩露排查NodeJS爬蟲記憶體洩露
- Pprof定位Go程式記憶體洩露Go記憶體洩露
- Handler 訊息機制以及記憶體洩漏記憶體
- Handler記憶體洩漏原因及解決方案記憶體
- win10驅動記憶體洩露如何解決_win10記憶體洩露處理方法Win10記憶體洩露
- netty 堆外記憶體洩露排查盛宴Netty記憶體洩露
- 乾貨分享:淺談記憶體洩露記憶體洩露
- 解決git記憶體洩露問題Git記憶體洩露
- Spring Boot heapdump洩露記憶體分析方法Spring Boot記憶體
- 線上記憶體洩露定位--memleak工具記憶體洩露
- java中如何檢視記憶體洩露Java記憶體洩露
- Android中使用Handler為何造成記憶體洩漏?Android記憶體
- 記一次"記憶體洩露"排查過程記憶體洩露
- 從Handler.post(Runnable r)再一次梳理Android的訊息機制(以及handler的記憶體洩露)Android記憶體洩露
- 簡單的記憶體“洩露”和“溢位”記憶體
- JAVA記憶體洩露的原因及解決Java記憶體洩露
- 一個 Vue 頁面的記憶體洩露分析Vue記憶體洩露
- 一個Vue頁面的記憶體洩露分析Vue記憶體洩露
- C程式記憶體洩露檢測工具——ValgrindC程式記憶體洩露
- Android效能最佳化之記憶體洩露Android記憶體洩露
- Python實現記憶體洩露排查的示例Python記憶體洩露
- 記憶體洩漏引起的 資料庫效能問題記憶體資料庫
- 排查Java記憶體洩露實戰(內附各種排查工具介紹)Java記憶體洩露
- 記一次 .NET 某工控軟體 記憶體洩露分析記憶體洩露