問題原因及解決方案
項(xiàng)目中有不少使用Handler的地方,有時候?yàn)榱朔奖阒苯親andler handler = new Handler()這種寫法,但是在Java中,非靜態(tài)的匿名InnerClass會持有一個OuterClass的隱式引用逛漫,而靜態(tài)內(nèi)部類則不會。在Android studio上會提示你如下的警告信息:
This Handler class should be static or leaks might occur
對此鳍侣,Google的Romain Guy給出了建議
所以針對Romain Guy的建議,圖1的的問題解決方案如下:
private static class BlurHandler extends Handler {
private final WeakReference<BlurController> mTarget;
public BlurHandler(BlurController controller) {
mTarget = new WeakReference<BlurController>(controller);
}
@Override
public void handleMessage(Message msg) {
BlurController controller = mTarget.get();
if (controller != null) {
Bitmap bitmap = (Bitmap) msg.obj;
if (bitmap != null && !bitmap.isRecycled()) {
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap,
bitmap.getWidth() / SCALE_RATIO,
bitmap.getHeight() / SCALE_RATIO,
false);
Bitmap blurBitmap = FastBlurUtil.doBlur(scaledBitmap, BLUR_RADIUS, true);
if (blurBitmap != null) {
controller.imgBigBg.setImageBitmap(blurBitmap);
}
}
}
}
}
ps:BlurHandler在BlurController類中吼拥,注意Romain Guy提到的OuterClass可以是任何類倚聚,可以是View,Activity凿可,或者XXUtils惑折,我這里就是BlurController。
給出了解決方案枯跑,會有到底是如何發(fā)生的內(nèi)存泄漏惨驶?
public class SampleActivity extends Activity {
private final Handler mLeakyHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// ...
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Post a message and delay its execution for 10 minutes.
mLeakyHandler.postDelayed(new Runnable() {
@Override
public void run() { /* ... */ }
}, 1000 * 60 * 10);
// Go back to the previous Activity.
finish();
}
}
當(dāng)activity被finish掉后,delayed message會在主線程的消息隊(duì)列中存在10分鐘后才會被執(zhí)行敛助,這個Message會持有一個SampleActivity中Handler的引用粗卜,而這個Handler也會持有一個SampleActivity的隱式引用,這個引用會一直存在直到message被執(zhí)行纳击,這樣會防止Activity的context被垃圾回收休建,但同時也會泄露application的資源。
小結(jié)
- 如果使用InnerClass评疗,請設(shè)置為static
- 對外部類持有個WeakReference