首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

三星手機 Android OOM 崩潰分析:AnimationDrawable 未停止導致內存洩漏

     編輯:程式設計綜合問答

崩潰日誌關鍵信息

E/art: Throwing OutOfMemoryError "Failed to allocate a 6144012 byte allocation with 5750804 free bytes and 5MB until OOM"
E/Resources: ExecutionException ... Caused by: java.lang.OutOfMemoryError
    at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
    at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
    at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1014)
    at android.content.res.Resources$RCCallable.call(Resources.java:1168)

崩潰位置:setContentView(R.layout.activity_dev_list) 時解析佈局資源耗盡內存。

根因定位

應用啟動時播放開機動畫使用 AnimationDrawable(幀動畫),動畫結束後未調用 stop(),導致:

  • 所有幀圖片常駐內存(Bitmap 不被回收)。
  • 動畫線程持續運行,持有對象引用阻礙 GC。
  • 三星設備內存管理較激進,觸發 OOM 閾值更低。

修正代碼

AnimationDrawable anim = (AnimationDrawable) imageView.getDrawable();
// 動畫結束監聽(API 16+)
anim.setCallback(new Drawable.Callback() {
    @Override public void invalidateDrawable(Drawable who) {}
    @Override public void scheduleDrawable(Drawable who, Runnable what, long when) {}
    @Override public void unscheduleDrawable(Drawable who, Runnable what) {
        // 動畫結束時釋放
        if (who instanceof AnimationDrawable) {
            ((AnimationDrawable) who).stop();
            who.setCallback(null); // 斷開引用鏈
        }
    }
});
anim.start();
// 或簡單場景:固定時長後手動停止
new Handler().postDelayed(() -> {
    if (anim != null && anim.isRunning()) {
        anim.stop();
        imageView.setImageDrawable(null); // 釋放 Bitmap
    }
}, anim.getDuration());

最佳實踐

  • 幀動畫幀數 > 10 或單幀 > 100KB 時,強制使用 VideoView/MediaPlayer 播放視頻替代。
  • 在 onDestroy/onStop 中統一調用 anim.stop() 並置空引用。
  • 使用 Glide/Picasso 加載大圖時啟用 .apply(RequestOptions().diskCacheStrategy(DiskCacheStrategy.NONE)) 避免內存峰值。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved