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

Android SharedPreferences 監聽器失效問題根因與解決方案

     編輯:程式設計綜合問答

SharedPreferences.OnSharedPreferenceChangeListener 採用 WeakHashMap 儲存監聽器,導致匿名內部類實例在方法結束後隨即符合 GC 回收條件,造成監聽器「前幾次生效、隨後失效」的詭異現象。核心解決之道是「以強引用持有監聽器實例」。

錯誤示範(匿名內部類)

// 錯誤:監聽器實例無強引用,極易被 GC 回收
prefs.registerOnSharedPreferenceChangeListener(
    new SharedPreferences.OnSharedPreferenceChangeListener() {
        @Override
        public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
            // 處理邏輯
        }
    }
);

正確寫法:成員變數持有強引用


public class MainActivity extends AppCompatActivity {
    // 1. 宣告為成員變數,生命週期綁定 Activity
    private SharedPreferences.OnSharedPreferenceChangeListener prefsListener;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);

        // 2. 實例化並賦值給成員變數
        prefsListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
            @Override
            public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
                Log.d("PREFS", "Changed key: " + key);
            }
        };

        // 3. 註冊
        prefs.registerOnSharedPreferenceChangeListener(prefsListener);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 4. 解註冊(雖非修復核心,但屬良好習慣)
        PreferenceManager.getDefaultSharedPreferences(this)
            .unregisterOnSharedPreferenceChangeListener(prefsListener);
    }
}

進階替代方案:PreferenceDataStore (API 24+)

Android 7.0 引入 PreferenceDataStore 允許完全自訂儲存邏輯,可搭配 LiveData 或 Flow 實現更現代的觀察模式,徹底規避 WeakHashMap 陷阱。

核心心法

「註冊的監聽器必須有強引用存活,直到明確解註冊為止。」

理解此機制,即可徹底解決 SharedPreferences 監聽器「莫名失效」的疑難雜症。

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