在同步完成后,我正在更改SyncAdapter中的SharedPreference,但是当我访问我的活动中的首选项时,我没有看到更新的值(而是看到旧的值).我究竟做错了什么?不同的语境
我的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中的一个静态函数,由Activity检查SharedPreference.这不返回在SyncAdapter中提交的值,而是返回旧值. (我的设置活动和其他活动也使用旧值.):
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的帮助,经过一些研究,拼凑了一个解决我的问题的自己.
没有更新相同上下文的DefaultSharedPreferences的原因是我已经指定了SyncService在AndroidManifest.xml中的自己的进程中运行(见下文).因此,从Android 2.3开始,其他进程被阻止访问更新的SharedPreferences文件(参见this answer和Context.MODE_MULTI_PROCESS
上的Android文档).
<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>
所以在SyncAdapter和我的应用程序的UI进程中访问SharedPreferences时,我必须设置MODE_MULTI_PROCESS.因为我在整个应用程序中广泛使用了PreferenceManager.getDefaultSharedPreferences(Context),所以我编写了一个实用程序方法,并用此方法替换了PreferenceManager.getDefaultSharedPreferences(Context)的所有调用(见下文).首选项文件的默认名称是硬编码的,并从the Android source code和this answer派生.
public static SharedPreferences getDefaultSharedPreferencesMultiProcess( Context context) { return context.getSharedPreferences( context.getPackageName() + "_preferences",Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS); }