2013-10-18 201 views
3

我一直在爲Android開發一段時間,目前正在與我的服務器進行同步。
快速介紹:我已閱讀關於同步適配器並知道它的作用,但我只想知道這是否是我的最佳選擇。與服務器同步

在我的應用程序,用戶可以點擊一個按鈕,通知的東西是對他很重要。點擊我想更新服務器以保存數據,並通知他的親屬。我的問題如下:用戶可以多次點擊該按鈕來打開和關閉,所以在這種情況下,我不想打開與服務器的通信,每次用戶單擊按鈕時,它甚至可能不會改變狀態其以前的狀態。

所以我的問題是:是否同步適配器正確的事情對我來說還是應該建立自己的類來說話,將檢查,以及接收緊急\非緊急像凌空的服務器。 如果有人可以澄清同步適配器的確切工作,我真的很感激它(這是否做我說的?)

如果有什麼不明確,我會很樂意澄清。 在此先感謝。

回答

1

Android同步框架應該非常適合您的使用。如果您根據需要標記同步,系統現在不會啓動它,但延遲一段時間。這樣,如果用戶切換回按鈕,您將能夠注意到沒有值已經改變。旁註:如果使用ContentProvider,它會在數據更改時自動通知SyncAdapter。如果需要,您也可以手動觸發同步。

同步框架做的只是調用一個方法(onPerformSync)。你可以自由實現它,只要你想。如果您認爲最後一個過於接近,或者發現數據是否真的發生了變化,或者已經恢復到原始值(例如,您可以在數據庫中保留「最後同步」值,那麼您可以比較它到onPerformSync方法中的當前值,如果相同,則不變)。

獎勵:您將節省電池電量,因爲同步框架儘可能按順序運行多個同步,您的用戶將能夠在集中的位置管理他們的帳戶(Android設置),禁用系統範圍內的同步(想想索尼的耐力模式,設置每個SyncAdapter在暫停時都處於活動狀態)。

+0

有一種方法來取消通過設置切換同步功能的能力?我擔心它會弄亂我的邏輯 – user2558461

+0

是的:看到屬性'android:userVisible'(http://developer.android.com/reference/android/content/AbstractThreadedSyncAdapter.html) –

+0

你能提供一些例子嗎?在我送你賞金之前? – user2558461

0

你也可以採取另一種方法,從服務器推送到設備,你的應用程序不需要隨時詢問更新,而是應該告訴服務器「嘿,我有東西給你」。

看一看谷歌雲端通訊。另一方面,如果您更喜歡用戶應該特別要求更新的方法,那麼您不需要擔心同步適配器 - 當然,這取決於您的應用程序的要求。

不過,我建議你看看GCM,這是更清潔和更優雅的服務器通知,然後不斷地問。

+0

我正在使用GCM進行通知。我目前正在詢問有關更新服務器的問題。沒有更新 – user2558461

+0

哦,奧奇,我誤解了;這應該是非常直接的,那麼只需發送一個通知給服務器,說明特定操作完成後發生了什麼;應用程序是否也假設處理脫機情況?或者離線時是否需要保存一些數據? –

+0

請仔細閱讀這個問題,我不想在用戶每次做某事時打開http套接字,因爲就像我所描述的那樣,他可能多次點擊/關閉同一個按鈕,甚至數據甚至可能不會改變。 – user2558461

0

當設備上的數據發生變化時運行同步適配器。該選項允許您將修改後的數據從設備發送到服務器,如果您需要確保服務器始終具有最新的設備數據,該選項尤其有用。如果您實際上將數據存儲在內容提供商中,則此選項很容易實現。如果您使用存根內容提供者,檢測數據更改可能會更困難。

在響應於用戶動作執行同步適配器。但是,爲了提供最佳的用戶體驗,您應該主要依靠更自動的選項之一。

您可以定期運行同步適配器,方法是設置一段時間以等待兩次運行之間的時間,或者在一天中的某些時間運行該時間段,或兩者都運行。定期運行同步適配器允許您大致匹配服務器的更新時間間隔。

0

運行同步適配器當內容提供者數據改變

public class MainActivity extends FragmentActivity { 
... 
// Constants 
// Content provider scheme 
public static final String SCHEME = "content://"; 
// Content provider authority 
public static final String AUTHORITY = "com.example.android.datasync.provider"; 
// Path for the content provider table 
public static final String TABLE_PATH = "data_table"; 
// Account 
public static final String ACCOUNT = "default_account"; 
// Global variables 
// A content URI for the content provider's data table 
Uri mUri; 
// A content resolver for accessing the provider 
ContentResolver mResolver; 
... 
public class TableObserver extends ContentObserver { 
    /* 
    * Define a method that's called when data in the 
    * observed content provider changes. 
    * This method signature is provided for compatibility with 
    * older platforms. 
    */ 
    @Override 
    public void onChange(boolean selfChange) { 
     /* 
     * Invoke the method signature available as of 
     * Android platform version 4.1, with a null URI. 
     */ 
     onChange(selfChange, null); 
    } 
    /* 
    * Define a method that's called when data in the 
    * observed content provider changes. 
    */ 
    @Override 
    public void onChange(boolean selfChange, Uri changeUri) { 
     /* 
     * Ask the framework to run your sync adapter. 
     * To maintain backward compatibility, assume that 
     * changeUri is null. 
     ContentResolver.requestSync(ACCOUNT, AUTHORITY, null); 
    } 
    ... 
} 
... 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    ... 
    // Get the content resolver object for your app 
    mResolver = getContentResolver(); 
    // Construct a URI that points to the content provider data table 
    mUri = new Uri.Builder() 
       .scheme(SCHEME) 
       .authority(AUTHORITY) 
       .path(TABLE_PATH) 
       .build(); 
    /* 
    * Create a content observer object. 
    * Its code does not mutate the provider, so set 
    * selfChange to "false" 
    */ 
    TableObserver observer = new TableObserver(false); 
    /* 
    * Register the observer for the data table. The table's path 
    * and any of its subpaths trigger the observer. 
    */ 
    mResolver.registerContentObserver(mUri, true, observer); 
    ... 
} 
... 

}

+0

你能解釋一下你宣佈的決賽嗎? – user2558461

+0

這些變量用於創建uri。 new Uri.Builder() .scheme(SCHEME) .authority(AUTHORITY) .path(TABLE_PATH) .build(); – akshay

+0

請注意,如果將SyncAdapter綁定到ContentProvider(因爲您只想觀察一個提供者),則不需要所有這些。您可以在'sync-adapter' XML中將它們與'android:contentAuthority'屬性綁定。每次您的ContentProvider通知其觀察者時,都會觸發掛起的同步。 –