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

时间:2014-10-16 15:45:21

标签: android sharedpreferences android-syncadapter

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

3 个答案:

答案 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 codethis 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>