SyncAdapter中提交的SharedPreference未在Activity中更新?

成功同步后,我正在更改并在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(); } } 

Application中调用的一个静态函数,用于检查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); } 

好吧,我通过@Titus的帮助弄清楚了自己并经过一些研究并拼凑出了我的问题的解决方案。

不更新相同ContextDefaultSharedPreferences的原因是我已经指定SyncServiceAndroidManifest.xml中的自己的进程中运行(见下文)。 因此,从Android 2.3开始,阻止其他进程访问更新的SharedPreferences文件(请参阅此答案和Context.MODE_MULTI_PROCESS上的Android文档)。

        

因此,在SyncAdapter和我的应用程序的UI过程中访问SharedPreferences时,我必须设置MODE_MULTI_PROCESS 。 因为我在整个应用程序中广泛使用了PreferenceManager.getDefaultSharedPreferences(Context) ,所以我编写了一个实用程序方法,并用这种方法替换了PreferenceManager.getDefaultSharedPreferences(Context)所有调用(见下文)。 首选项文件的默认名称是硬编码的,并从Android源代码和此答案派生。

 public static SharedPreferences getDefaultSharedPreferencesMultiProcess( Context context) { return context.getSharedPreferences( context.getPackageName() + "_preferences", Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS); } 

由于SharedPreferences不是进程安全的,我不建议在另一个进程中使用AbstractThreadedSyncAdapter,除非你真的需要它。

为什么我的应用程序需要多个进程?

从您在清单中声明的​​服务中删除android:process=":sync"

       

在我的情况下,我试图从BroadcastReceiver发起的服务访问SharedPreferences。

我从AndroidManifest.xml中的声明中删除了android:process=":remote"以使其工作。