成功同步后,我正在更改并在SyncAdapter中提交SharedPreference,但是当我在Activity中访问首选项时,我没有看到更新的值(相反,我看到的是旧值)。我究竟做错了什么?不同的背景?
我在SyncAdapter中更新首选项:
class SyncAdapter extends AbstractThreadedSyncAdapter {
private int PARTICIPANT_ID;
private final Context mContext;
private final ContentResolver mContentResolver;
public SyncAdapter(Context context, boolean autoInitialize) {
super(context, autoInitialize);
mContext = context;
mContentResolver = context.getContentResolver();
}
public SyncAdapter(Context context, boolean autoInitialize, boolean allowParallelSyncs) {
super(context, autoInitialize, allowParallelSyncs);
mContext = context;
mContentResolver = context.getContentResolver();
}
@Override
public void onPerformSync(Account account, Bundle extras, String authority,
ContentProviderClient provider, SyncResult syncResult) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
PARTICIPANT_ID = Integer.parseInt(prefs.getString("participant_id", "0"));
if (success) {
// save and set the new participant id
PARTICIPANT_ID = newParticipantId;
prefs.edit().putString("participant_id", String.valueOf(newParticipantId)).commit();
}
}
}
服务使用ApplicationContext初始化SyncAdapter:
public class SyncService extends Service {
private static final Object sSyncAdapterLock = new Object();
private static SyncAdapter sSyncAdapter = null;
@Override
public void onCreate() {
synchronized (sSyncAdapterLock) {
if (sSyncAdapter == null) {
sSyncAdapter = new SyncAdapter(getApplicationContext(), false);
}
}
}
@Override
public IBinder onBind(Intent intent) {
return sSyncAdapter.getSyncAdapterBinder();
}
}
由Activity调用的一个静态函数,用于检查SharedPreference。这不会返回SyncAdapter中提交的值,而是返回旧值。 (我的SettingsActivity和其他活动也使用旧值。):
public static boolean isUserLoggedIn(Context ctx) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
int participantId = Integer.parseInt(prefs.getString("participant_id", "0"));
LOGD("dg_Utils", "isUserLoggedIn.participantId: " + participantId);// TODO
if (participantId <= 0) {
ctx.startActivity(new Intent(ctx, LoginActivity.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
return false;
}
return true;
}
更新:当我完全关闭应用时,我会获得新值(从正在运行的应用中滑动)。我还有一个SharedPreferenceChangeListener,在更新首选项时不会触发它。
private final SharedPreferences.OnSharedPreferenceChangeListener mParticipantIDPrefChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (key.equals("participant_id")) {
LOGI(TAG, "participant_id has changed, requesting to restart the loader.");
mRestartLoader = true;
}
}
};
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// subscribe to the participant_id change lister
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
PARTICIPANT_ID = Integer.parseInt(prefs.getString("participant_id", "0"));
prefs.registerOnSharedPreferenceChangeListener(mParticipantIDPrefChangeListener);
}
答案 0 :(得分:16)
好的,我在@Titus的帮助下找到了自己,经过一些研究并拼凑出了我的问题的解决方案。
同一DefaultSharedPreferences
的{{1}}未更新的原因是我已在Context
指定SyncService
在其自己的流程中运行(请参阅下文) )。因此,从Android 2.3开始,阻止其他进程访问更新的AndroidManifest.xml
文件(请参阅this answer上的Context.MODE_MULTI_PROCESS
和Android文档)。
SharedPreferences
因此,在我的应用的 <service
android:name=".sync.SyncService"
android:exported="true"
android:process=":sync"
tools:ignore="ExportedService" >
<intent-filter>
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="@xml/syncadapter" />
</service>
和UI流程中访问MODE_MULTI_PROCESS
时,我必须设置SharedPreferences
。因为我在整个应用程序中广泛使用了SyncAdapter
,所以我编写了一个实用程序方法,并用这种方法替换了PreferenceManager.getDefaultSharedPreferences(Context)
的所有调用(见下文)。首选项文件的默认名称是硬编码的,源自the Android source code和this answer。
PreferenceManager.getDefaultSharedPreferences(Context)
答案 1 :(得分:0)
由于SharedPreferences不是进程安全的,我不建议在另一个进程中使用AbstractThreadedSyncAdapter,除非你真的需要它。
Why do i need multiple processes in my application?
<强>解决方案强>
从您在清单中声明的服务中删除android:process=":sync"
!
<service
android:name=".sync.SyncService"
android:exported="true"
android:process=":sync"
tools:ignore="ExportedService" >
<intent-filter>
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="@xml/syncadapter" />
</service>
答案 2 :(得分:0)
在我的情况下,我试图从BroadcastReceiver发起的服务访问SharedPreferences。
我从AndroidManifest.xml中的声明中删除了android:process=":remote"
以使其正常工作。
<receiver
android:process=":remote"
android:name=".Alarm">
</receiver>