This Handler class should be static or leaks might occur

問題原因及解決方案

項目中有不少使用Handler的地方,有時候為了方便直接Handler handler = new Handler()這種寫法,但是在Java中,非靜態(tài)的匿名InnerClass會持有一個OuterClass的隱式引用,而靜態(tài)內(nèi)部類則不會。在Android studio上會提示你如下的警告信息:

This Handler class should be static or leaks might occur

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

對此,Google的Romain Guy給出了建議


0-2.png

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

小結(jié)

  • 如果使用InnerClass,請設(shè)置為static
  • 對外部類持有個WeakReference

參考文章

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容