如何检测偏好设置是否已更改?

77

我有一个继承PreferenceActivity的类用于展示我的应用程序的首选项屏幕。是否可以检查是否对首选项进行了任何更改?

这有助于...

http://developer.android.com/reference/android/content/SharedPreferences.OnSharedPreferenceChangeListener.html

其他相关帖子: SharedPreferences.onSharedPreferenceChangeListener没有被一致地调用


public class PreferenceClass extends PreferenceActivity {

    OnSharedPreferenceChangeListener listener;

    public void onCreate(Bundle savedInstanceState) {
        SharedPreferences prefs = this.getSharedPreferences("settings", 0);
        listener = new SharedPreferences.OnSharedPreferenceChangeListener() {

            public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
                int flag = 1;
            }
        };
        prefs.registerOnSharedPreferenceChangeListener(listener);
        super.onCreate(null);
        addPreferencesFromResource(R.xml.settings);
    }
}

我看到这个问题有很多可能的方向,这取决于你的总体目标。你能具体说明一下你何时进行检查以及最终目的是什么吗? - R Hughes
@RHughes 我只是想每次有更改时做一些事情...刚刚找到了这个链接https://dev59.com/yHE85IYBdhLWcg3w64IA...但仍然无法使其工作...监听器中的方法从未被调用过...有任何想法吗??? - mixkat
不看代码,我只能猜测你正在犯我总是犯的错误。我创建了一个很好的监听器,然后忘记将它附加到正确的对象上。另外,请确保在onCreate()方法中将监听器附加到对象上,或者至少在实际需要侦听器进行侦听之前运行代码时将其附加。 - R Hughes
@RHughes,我正在将监听器附加到对象上...不知道是哪里出了问题...肯定是在创建时...无论如何感谢您的回复... - mixkat
2个回答

68
SharedPreferences.OnSharedPreferenceChangeListener spChanged = new
                           SharedPreferences.OnSharedPreferenceChangeListener() {
            @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
            String key) {
        // your stuff here
    }
};
在你的PreferenceActivity中,将其作为PreferenceActivity类的成员,并在PreferenceActivity.onCreate()方法中执行registerOnSharedPreferenceChangeListener(spChanged)。这就是我所做的,我从未遇到过问题。否则,问题可能出在你监听器中条件检查上。请发布代码。
编辑:
根据你发布的代码,你应该将prefs作为类成员变量以使其具有全局范围。使用PreferenceManager.getDefaultSharedPreferences(getApplicationContext())而不是getSharedPreferences,因为你没有创建该文件。要创建一个文件,你需要使用PreferenceManager。要获取PreferenceManager,请使用Activity.getPreferenceManager()

1
@sugarynugs 监听器是这个类的实例变量,只是为了避免它被垃圾回收。 - mixkat
1
变量声明在哪里?它是“全局”的吗?另外,错误的代码已发布...在监听器内部的那一部分。 - techi.services
不要忘记使用.unregisterOnSharedPreferenceChangeListener取消注册监听器!!! - babay
@babay:请问您是否知道,如果监听器是在Application类中实现的,是否有必要尝试注销它?(这样做会非常困难-Application类没有onStop()或onDestroy()方法。) - RenniePet
1
@RenniePet,不必注销在Application类中注册的首选项监听器。例如,在Activity类中不注销监听器,则垃圾回收器将不会在活动关闭后释放由Activity对象分配的内存(首选项管理器具有对监听器的引用,监听器具有对Activity的引用)。 但是,在Application类中,您不会遇到这种情况。 - babay
显示剩余3条评论

67

在你的PreferenceActivity类中,实现 SharedPreferences.OnSharedPreferenceChangeListener 接口。将所需的 onSharedPreferenceChanged 方法添加到你的类中,并在 onCreate 中进行注册。

参考代码如下:

public class MyPreferences extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.fw_preferences); //deprecated
        PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        // handle the preference change here
    }

}

1
你会如何重构代码中已经被弃用的这一行?addPreferencesFromResource(R.xml.fw_preferences); //已弃用 - mattecalcio
1
@mattecalcio 我知道我来晚了,但这是加载设置xml的新方法:https://dev59.com/pGw15IYBdhLWcg3wG4AJ#13441715 - user1318194
2
在MainActivity的onDestroy()方法中执行unregisterOnSharedPreferenceChangeListener(this)是一个好的做法吗? - Andrii Kovalchuk
1
你的答案很棒,但文档中还提到:在简历中添加注册部分,并在暂停时添加注销部分以进行垃圾回收。再次感谢。https://developer.android.com/guide/topics/ui/settings.html#ReadingPrefs - mehmet
实现接口OnSharedPreferenceChangeListener,并在onResume上注册监听器,onPause上取消注册。 - MRodrigues
不要忘记在onDestroy中调用PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this); 或者按照@MRodrigues上面的方式实现。 - Cícero Moura

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接