在实现OnSharedPreferenceChangeListener接口的android服务中使用线程/任务时,首选项屏幕中所做的更改不会反映回android服务中的线程/任务对象。
我想完成两件事:
构建和初始化MyTask时,应加载SharedPreference数据。
发生首选项更改时,必须使用首选项屏幕中设置的新首选项值更新MyTask对象。
问题是:首选项初始化和首选项更改不会反映到MyTask对象。
这是我的设置(仅提到必要部分):
MyService.class:
public class MyService extends Sevice {
private MyTask myTask;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!serviceStarted) {
serviceStarted = true;
myTask = new MyTask(this);
Thread t = new Thread(myTask);
t.start();
}
return Service.START_STICKY;
}
@Override
public void onDestroy() {
myTask.cancel();
super.onDestroy();
}
}
MyTask.class:
public MyTask implements Runnable, OnSharedPreferenceChangeListener {
private Context mContext;
private boolean mCancelled;
public MyTask(Context context) {
mContext = context;
}
@Override
public void run() {
while(!mCancelled) {
// do something
}
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
// FIXME: DOESN'T GET CALLED after change in preference!!!!
Log.d(TAG, "Key= " + key);
}
public void cancel() {
mCancelled = true;
}
}
preference_devices.xml:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory
android:key="pref_category_devices"
android:title="@string/pref_category_devices_title" >
<CheckBoxPreference
android:defaultValue="true"
android:key="pref_devices_server"
android:title="@string/pref_devices_server_title" />
</PreferenceCategory>
</PreferenceScreen>
我尝试将SharedPreferences侦听器对象编码为MyTask类的成员字段,并从提供的上下文中注册/取消注册侦听器,但这也不起作用。这些变化也不起作用:
MyTask.class(使用SharedPreference侦听器作为类的字段成员):
public MyTask implements Runnable {
private Context mContext;
private boolean mCancelled;
private boolean mServerEnabled;
private SharedPreferences mPrefs;
private SharedPreferences.OnSharedPreferenceChangeListener
mPreferenceListener;
public MyTask(Context context) {
mContext = context;
mPrefs = mContext.getSharedPreferences("pref_category_devices",
Context.MODE_PRIVATE);
mPreferenceListener = new OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(
SharedPreferences sharedPreferences, String key) {
// FIXME: DOESN'T GET CALLED after change in preference!!!!
Log.d(TAG, "Key= " + key);
}
};
mPrefs.registerOnSharedPreferenceChangeListener(mPreferenceListener);
// set the initial value of the preference setting
mServerEnabled = mPrefs.getBoolean("pref_devices_server", false);
}
@Override
public void run() {
while(!mCancelled) {
// do something
}
}
public void cancel() {
mCancelled = true;
}
}
我现在已经到了将计算机扔出窗外的地步:(
非常感谢任何正确方向的帮助:)
编辑:在代码中
mPrefs = mContext.getSharedPreferences("pref_category_devices", Context.MODE_PRIVATE);
我假设第一个参数应该是首选项文件的首选项类别名称,例如:“pref_category_devices”。这是不正确的!第一个参数必须是共享首选项文件名。这并没有解决问题,但至少现在你知道不要陷入这个陷阱。
===解决方案:=== 在此行下方查看Mr_and_Mrs_D +代码的答案:
MyTask中的更改:
mPrefs = mContext.getSharedPreferences("pref_category_devices",
Context.MODE_PRIVATE);
成:
mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
mPreferenceListener = new OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals("preference_name_here")) {
mPrefValue = sharedPreferences.getBoolean(key, false);
// do something with boolean pref value
}
}
};
mPrefs.registerOnSharedPreferenceChangeListener(myPreferenceListener);
其中mPrefValue是MyTask中boolean类型的字段成员,需要在“preference_name_here”首选项更改时设置。
答案 0 :(得分:1)
更改:
private volatile boolean mCancelled; //otherwise the myTask thread may never stop
对于你的问题:
if (!serviceStarted) {
serviceStarted = true;
myTask = new MyTask(this);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
sp.registerOnSharedPreferenceChangeListener(myTask); //err, you must register
Thread t = new Thread(myTask); t.start();
}
Docs:
当用户与其进行交互时,这些首选项将自动保存到SharedPreferences。要检索此活动中的首选项层次结构将使用的SharedPreferences实例,使用与此活动相同的包中的上下文调用getDefaultSharedPreferences(android.content.Context)。
[强调我的]
编辑:你的第二个片段可能会失败,因为你得到了错误的共享首选项 - 你必须得到默认的 - 我认为它失败了因为:
SharedPreferences.onSharedPreferenceChangeListener not being called consistently