This Handler class should be static or leaks might occur

問題原因及解決方案

項(xiàng)目中有不少使用Handler的地方,有時(shí)候?yàn)榱朔奖阒苯親andler handler = new Handler()這種寫法,但是在Java中,非靜態(tài)的匿名InnerClass會(huì)持有一個(gè)OuterClass的隱式引用,而靜態(tài)內(nèi)部類則不會(huì)。在Android studio上會(huì)提示你如下的警告信息:

This Handler class should be static or leaks might occur

屏幕快照 2018-01-10 下午3.09.36.png

對(duì)此,Google的Romain Guy給出了建議


0-2.png

所以針對(duì)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。
給出了解決方案,會(huì)有到底是如何發(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會(huì)在主線程的消息隊(duì)列中存在10分鐘后才會(huì)被執(zhí)行,這個(gè)Message會(huì)持有一個(gè)SampleActivity中Handler的引用,而這個(gè)Handler也會(huì)持有一個(gè)SampleActivity的隱式引用,這個(gè)引用會(huì)一直存在直到message被執(zhí)行,這樣會(huì)防止Activity的context被垃圾回收,但同時(shí)也會(huì)泄露application的資源。

小結(jié)

  • 如果使用InnerClass,請(qǐng)?jiān)O(shè)置為static
  • 對(duì)外部類持有個(gè)WeakReference

參考文章

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。