2014-10-16 18 views
13

Tôi đang thay đổi và cam kết SharedPreference trong SyncAdapter sau khi đồng bộ hóa thành công, nhưng tôi không thấy giá trị cập nhật khi tôi truy cập tùy chọn trong Hoạt động của tôi (thay vì tôi thấy giá trị cũ). Tôi đang làm gì sai? Các bối cảnh khác nhau?SharedPreference được cam kết trong SyncAdapter không được cập nhật trong Hoạt động?

SyncAdapter của tôi, nơi tôi cập nhật các ưu tiên:

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(); 
     } 
    } 
} 

Các dịch vụ khởi tạo SyncAdapter với ApplicationContext:

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(); 
    } 
} 

Một chức năng tĩnh trong ứng dụng gọi bằng các Hoạt động để kiểm tra các SharedPreference. Điều này không trả về giá trị đã cam kết trong SyncAdapter, mà là giá trị cũ. (SettingsActivity My và các hoạt động khác cũng sử dụng giá trị cũ.):

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; 
} 

UPDATE: Tôi nhận được giá trị mới khi tôi hoàn toàn đóng ứng dụng (swipe nó từ các ứng dụng đang chạy). Tôi cũng có một SharedPreferenceChangeListener, nó không được kích hoạt khi tùy chọn được cập nhật.

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

Từ mã bạn đã đăng, có vẻ như bạn không bao giờ gọi 'startSync()' trên 'SyncAdapter' có nghĩa là phương thức' onPerformSync (...) 'không thực thi và sở thích không bao giờ thay đổi. – Titus

+0

@Titus Một nơi nào đó tôi làm và 'onPerformSync()' chắc chắn được thực hiện. Nó cũng sử dụng giá trị mới trong các đồng bộ tiếp theo. Tôi đã phát hiện ra rằng 'SyncService' đang chạy trong một quá trình riêng biệt (' '). Bây giờ tôi đang cố gắng tìm ra cách sử dụng 'MODE_MULTI_PROCESS' với' PreferenceManager.getDefaultSharedPreferences() '. – matsch

+0

Bạn có thể sử dụng 'prefs = mContext.getSharedPreferences (" myAppPrefs ", Context.MODE_MULTI_PROCESS);' [Here] (http://developer.android.com/reference/android/content/Context.html#getSharedPreferences (java.lang .String, int)) là tài liệu. – Titus

Trả lời

16

Ok, tôi đã tự tìm ra và giúp tôi giải quyết vấn đề của mình.

Lý do tại sao các DefaultSharedPreferences của cùng Context không được cập nhật là tôi đã xác định các SyncService để chạy trong quá trình riêng của mình trong AndroidManifest.xml (xem dưới đây). Do đó, bắt đầu từ Android 2.3, quá trình khác bị chặn truy cập vào tệp SharedPreferences được cập nhật (xem this answer và tài liệu Android trên Context.MODE_MULTI_PROCESS).

<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> 

Vì vậy, tôi đã phải thiết lập MODE_MULTI_PROCESS khi truy cập vào SharedPreferences cả trong SyncAdapter và trong quá trình giao diện người dùng của ứng dụng của tôi. Bởi vì tôi đã sử dụng PreferenceManager.getDefaultSharedPreferences(Context) rộng rãi trong suốt ứng dụng tôi đã viết một phương pháp tiện ích và thay thế tất cả các cuộc gọi của PreferenceManager.getDefaultSharedPreferences(Context) bằng phương pháp này (xem bên dưới). Tên mặc định của tệp tùy chọn được mã hóa cứng và có nguồn gốc từ the Android source codethis answer.

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

Theo http://stackoverflow.com/a/6310080/8524 đoạn mã trên sẽ nhận được cùng một đối tượng 'SharedPreferences' như' SharedPreferences.getDefaultSharedPreferences() 'hiện . – Diederik

+1

Có, nó sẽ nhận được cùng một đối tượng, nhưng với bộ chỉnh sửa 'Context.MODE_MULTI_PROCESS'. Tôi đang liên kết với cùng một câu trả lời bạn đang ở trong đoạn cuối của tôi. – matsch

+0

Ngoài câu trả lời của bạn, tôi nghĩ. Tôi đã thêm nhận xét trong trường hợp bất kỳ ai (như tôi) đã sử dụng 'SharedPreferences.getDefaultSharedPreferences()' để nhận các tùy chọn được chia sẻ và sau đó nhận ra rằng họ cần truy cập nhiều quy trình. – Diederik

0

Vì SharedPreferences không an toàn quá trình, tôi sẽ không khuyên bạn nên sử dụng AbstractThreadedSyncAdapter trong một quy trình khác trừ khi bạn thực sự cần nó.

Why do i need multiple processes in my application?

Giải pháp

Di android:process=":sync" từ các dịch vụ mà bạn khai báo trong biểu hiện của bạn!

<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> 
+0

Cảm ơn nó đã làm việc cho tôi. –

0

Trong trường hợp của tôi, tôi đang cố truy cập SharedPreferences từ dịch vụ do BroadcastReceiver khởi chạy.

Tôi đã xóa android:process=":remote" khỏi tuyên bố trong AndroidManifest.xml để làm cho nó hoạt động.

<receiver 
    android:process=":remote" 
    android:name=".Alarm"> 
</receiver> 
Các vấn đề liên quan