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

Android App 鎖屏後無響應、GC 頻繁的內存洩漏排查與 onSaveInstanceState 正確使用

     編輯:程式設計綜合問答

現象分析

  • Logcat 持續打印 GC_CONCURRENT freed ... 7% free:堆內存佔用極高,GC 頻繁回收效果差,主線程頻繁阻塞導致 ANR/無響應。
  • 鎖屏 1 分鐘後無響應:進程進入後台,系統回收內存、降低 CPU 優先級,內存洩漏對象無法釋放,恢復時需大量 GC/內存整理,卡死 10 秒+。
  • System.exit(0) 強制退出導致 onDestroy 不執行:繞過生命周期,資源洩漏、數據未保存。

核心排查方向

  1. 內存洩漏檢測:
    • Android Studio Profiler → Heap Dump → 分析 Activity/Context 殘留實例。
    • LeakCanary 自動檢測並報告洩漏鏈路。
    • 常見洩漏源:靜態持有 View/Context、未註冊監聽器/廣播、Handler 延遲消息未移除、內部類持有外部類引用。
  2. 後台生命周期管理:
    • 實現 onSaveInstanceState(Bundle) 保存關鍵 UI 狀態(輸入文本、滾動位置、選中項)。
    • onPause/onStop 釋放重型資源(Bitmap、數據庫連接、網絡請求取消、傳感器註銷)。
    • 避免在 onDestroy 做關鍵清理(進程被殺時不調用)。

onSaveInstanceState 標準實現


@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
    super.onSaveInstanceState(outState);
    // 保存 UI 狀態
    outState.putString("input_text", editText.getText().toString());
    outState.putInt("scroll_position", listView.getFirstVisiblePosition());
    outState.putParcelable("selected_item", selectedItem);
    // 保存業務數據
    outState.putSerializable("draft_model", draftModel);
}

@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    editText.setText(savedInstanceState.getString("input_text"));
    listView.setSelection(savedInstanceState.getInt("scroll_position"));
    selectedItem = savedInstanceState.getParcelable("selected_item");
    draftModel = (DraftModel) savedInstanceState.getSerializable("draft_model");
}

Application 管理 Activity 棧的正確退出模式


public class MyApp extends Application {
    private final List activities = new ArrayList<>();

    public void registerActivity(Activity activity) {
        activities.add(activity);
    }

    public void unregisterActivity(Activity activity) {
        activities.remove(activity);
    }

    public void exitApp() {
        // 副本遍歷,避免 ConcurrentModificationException
        for (Activity activity : new ArrayList<>(activities)) {
            if (!activity.isFinishing()) {
                activity.finish(); // 正常調用 finish(),走完生命周期
            }
        }
        // 不要 System.exit(0)!讓系統自然回收進程
    }
}

// BaseActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ((MyApp) getApplication()).registerActivity(this);
}

@Override
protected void onDestroy() {
    ((MyApp) getApplication()).unregisterActivity(this);
    super.onDestroy();
}

總結

鎖屏後無響應 + 高佔用 GC = **嚴重內存洩漏**。
1. 用 LeakCanary/Profiler 定位洩漏點並修復。
2. 正確實現 onSaveInstanceState 保存狀態,onPause 釋放資源。
3. **禁止 System.exit(0)**,用 finish() 讓 Activity 走完生命周期,系統自動管理進程。
4. 後台長運行任務用 WorkManager/Foreground Service,而非常駐 Activity。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved