You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AndroidX迁移后子类SharedPreferences空指针问题

AndroidX迁移:PreferenceActivity转FragmentActivity+PreferenceFragmentCompat时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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 18:50:53