Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// do something.
}
}
```
當咱們這樣建立`Handler`的時候`Android Lint`會提示咱們這樣一個`warning: In Android, Handler classes should be static or leaks might occur.`。
一直以來沒有仔細的去分析泄露的緣由,先把主要緣由列一下:
- `Android`程序第一次建立的時候,默認會建立一個`Looper`對象,`Looper`去處理`Message Queue`中的每一個`Message`,主線程的`Looper`存在整個應用程序的生命週期.
- `Hanlder`在主線程建立時會關聯到`Looper`的`Message Queue`,`Message`添加到消息隊列中的時候`Message(排隊的Message)`會持有當前`Handler`引用,當`Looper`處理到當前消息的時候,會調用`Handler#handleMessage(Message)`.就是說在`Looper`處理這個`Message`以前,會有一條鏈`MessageQueue -> Message -> Handler -> Activity`,因爲它的引用致使你的`Activity`被持有引用而沒法被回收`
- **在java中,no-static的內部類會隱式的持有當前類的一個引用。static的內部類則沒有。**
##具體分析
```java
public class SampleActivity extends Activity {
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// do something
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 發送一個10分鐘後執行的一個消息
mHandler.postDelayed(new Runnable() {
@Override
public void run() { }
}, 600000);
// 結束當前的Activity
finish();
}
```
在`finish()`的時候,該`Message`尚未被處理,`Message`持有`Handler`,`Handler`持有`Activity`,這樣會致使該`Activity`不會被回收,就發生了內存泄露.
##解決方法
- 經過程序邏輯來進行保護。
- 若是`Handler`中執行的是耗時的操做,在關閉`Activity`的時候停掉你的後臺線程。線程停掉了,就至關於切斷了`Handler`和外部鏈接的線,`Activity`天然會在合適的時候被回收。
- 若是`Handler`是被`delay`的`Message`持有了引用,那麼在`Activity`的`onDestroy()`方法要調用`Handler`的`remove*`方法,把消息對象從消息隊列移除就好了。
- 關於`Handler.remove*`方法
- `removeCallbacks(Runnable r)` ——清除r匹配上的Message。
- `removeC4allbacks(Runnable r, Object token)` ——清除r匹配且匹配token(Message.obj)的Message,token爲空時,只匹配r。
- `removeCallbacksAndMessages(Object token)` ——清除token匹配上的Message。
- `removeMessages(int what)` ——按what來匹配
- `removeMessages(int what, Object object)` ——按what來匹配
咱們更多須要的是清除以該`Handler`爲`target`的全部`Message(Callback)`就調用以下方法便可`handler.removeCallbacksAndMessages(null)`;
- 將`Handler`聲明爲靜態類。
靜態類不持有外部類的對象,因此你的`Activity`能夠隨意被回收。可是不持有`Activity`的引用,如何去操做`Activity`中的一些對象? 這裏要用到弱引用
```java
public class MyActivity extends Activity {
private MyHandler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new MyHandler(this);
}
@Override
protected void onDestroy() {
// Remove all Runnable and Message.
mHandler.removeCallbacksAndMessages(null);
super.onDestroy();
}
static class MyHandler extends Handler {
// WeakReference to the outer class's instance.
private WeakReference<MyActivity> mOuter;
public MyHandler(MyActivity activity) {
mOuter = new WeakReference<MyActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
MyActivity outer = mOuter.get();
if (outer != null) {
// Do something with outer as your wish.
}
}
}
}java