AndroidX迁移后子类SharedPreferences空指针问题
问题背景
将继承PreferenceActivity的旧代码迁移至AndroidX框架,改用FragmentActivity嵌套PreferenceFragmentCompat实现,但在获取SharedPreferences实例时触发NullPointerException,已知需在Fragment创建完成后调用相关方法,但不确定具体时机。
原PreferenceActivity实现代码
import android.preference.PreferenceActivity; ... public class LatinIMESettings extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener, DialogInterface.OnDismissListener { @Override protected void onCreate(Bundle icicle) { ... SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); prefs.registerOnSharedPreferenceChangeListener(this); } ... }
迁移后的FragmentActivity实现代码
import androidx.fragment.app.FragmentActivity; import androidx.preference.PreferenceFragmentCompat; ... public class LatinIMESettings extends FragmentActivity implements SharedPreferences.OnSharedPreferenceChangeListener, DialogInterface.OnDismissListener { static class LatinIMESettingsFragment extends PreferenceFragmentCompat { @Override public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) { setPreferencesFromResource(R.xml.prefs, rootKey); } } LatinIMESettingsFragment fragment = new LatinIMESettingsFragment(); @Override protected void onCreate(Bundle icicle) { fragment = new LatinIMESettingsFragment(); ... SharedPreferences prefs = fragment.getPreferenceManager().getSharedPreferences(); prefs.registerOnSharedPreferenceChangeListener(this); } ... }
问题原因
在Activity的onCreate方法中直接调用fragment.getPreferenceManager().getSharedPreferences()时,Fragment尚未完成依附到Activity的流程,PreferenceManager还未初始化完成,导致返回null触发空指针异常。
解决方案
以下两种时机可安全获取SharedPreferences并注册监听器:
方案1:在Fragment的onViewCreated中处理
将监听器注册逻辑移至PreferenceFragmentCompat的onViewCreated方法,此时Fragment已完成视图初始化,PreferenceManager就绪:
static class LatinIMESettingsFragment extends PreferenceFragmentCompat { @Override public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) { setPreferencesFromResource(R.xml.prefs, rootKey); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); ((LatinIMESettings) requireActivity()).registerPreferenceListener(prefs); } } // 在Activity中添加注册方法 public void registerPreferenceListener(SharedPreferences prefs) { prefs.registerOnSharedPreferenceChangeListener(this); }
方案2:在Activity的onStart/onResume中处理
等Fragment完全依附并初始化后,在Activity的生命周期方法中获取实例:
@Override protected void onStart() { super.onStart(); if (fragment.isAdded()) { SharedPreferences prefs = fragment.getPreferenceManager().getSharedPreferences(); prefs.registerOnSharedPreferenceChangeListener(this); } }
额外注意事项
务必在合适的生命周期方法中注销监听器,避免内存泄漏:
@Override protected void onDestroy() { super.onDestroy(); if (fragment.isAdded()) { SharedPreferences prefs = fragment.getPreferenceManager().getSharedPreferences(); prefs.unregisterOnSharedPreferenceChangeListener(this); } }
内容的提问来源于stack exchange,提问作者user23619351
相关产品推荐
相关产品推荐

