將資料項目與 Data Layer API 同步處理

DataItem 定義了系統用來同步處理手持裝置和穿戴式裝置資料的介面。DataItem 通常包含下列元件:

  • 酬載:可用資料設定的位元組陣列,用來執行專屬的物件序列化和去序列化作業。酬載大小上限為 100 KB。
  • 路徑:必須以正斜線開頭的專用字串,例如 "/path/to/data"

注意:Data Layer API 只能傳送訊息並與 Android 手機或 Wear OS 手錶同步處理資料。如果 Wear OS 裝置與 iOS 裝置配對,Data Layer API 將無法運作。

因此,請不要使用 Data Layer API 做為與網路通訊的主要方式,而是改用與行動應用程式的模式相同,但有些微差異的方式

開發人員通常不會直接實作 DataItem,而是:

  1. 建立 PutDataRequest 物件,指定可以專門識別該項目的字串路徑。
  2. 呼叫 setData() 設定酬載。
  3. 如果同步處理出現延遲會影響使用者體驗,請呼叫 setUrgent()
  4. 使用 DataClient 類別的 putDataItem 方法要求系統建立資料項目。

系統要求資料項目時,會傳回能夠正確實作 DataItem 介面的物件。不過比起使用 setData() 處理原始位元組,我們建議使用資料對應,以類似 Bundle 的介面顯示資料項目。

詳情請參閱 DataLayer 範例應用程式。

使用資料對應同步處理資料

請儘可能使用 DataMap 類別。這樣做就能以 Android Bundle 的形式處理資料項目,讓系統為您進行物件序列化和去序列化,您也可以透過鍵/值組合操控資料。

使用資料對應:

  1. 建立 PutDataMapRequest 物件,設定資料項目的路徑。

    注意:路徑字串是資料項目的唯一識別碼,可用來從連線的任一端進行存取。路徑必須以正斜線開頭。如果應用程式內有使用階層式資料,請建立符合資料結構的路徑配置。

  2. 呼叫 PutDataMapRequest.getDataMap() 取得可供設定值的資料對應。
  3. 使用 put...() 方法設定資料對應的值,例如 putString()
  4. 如果同步處理出現延遲會影響使用者體驗,請呼叫 setUrgent()
  5. 呼叫 PutDataMapRequest.asPutDataRequest() 取得 PutDataRequest 物件。
  6. 使用 DataClient 類別的 putDataItem 方法要求系統建立資料項目。

    注意:如果手持裝置和穿戴式裝置連線中斷,系統會在連線恢復後緩衝並同步處理資料。

以下範例中的 increaseCounter() 方法可以說明如何建立資料對應並加入資料:

Kotlin

private const val COUNT_KEY = "com.example.key.count"

class MainActivity : Activity() {

    private lateinit var dataClient: DataClient
    private var count = 0
    ...
    // Create a data map and put data in it
    private fun increaseCounter() {
        val putDataReq: PutDataRequest = PutDataMapRequest.create("/count").run {
            dataMap.putInt(COUNT_KEY, count++)
            asPutDataRequest()
        }
        val putDataTask: Task<DataItem> = dataClient.putDataItem(putDataReq)
    }
    ...
}

Java

public class MainActivity extends Activity {
    private static final String COUNT_KEY = "com.example.key.count";
    private DataClient dataClient;
    private int count = 0;
    ...
    // Create a data map and put data in it
    private void increaseCounter() {
        PutDataMapRequest putDataMapReq = PutDataMapRequest.create("/count");
        putDataMapReq.getDataMap().putInt(COUNT_KEY, count++);
        PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
        Task<DataItem> putDataTask = dataClient.putDataItem(putDataReq);
    }
  ...
}

如何處理 Tasks 的詳情請見 參考文件

設定 DataItem 的優先順序

DataClient API 可用於緊急要求同步處理 DataItem 物件。一般而言,系統會延遲資料項目提交到 Wear OS 網路的時間,藉此提升使用者裝置的電池續航力,但如果延遲同步處理資料項目會對使用者體驗造成負面影響,您可以標示為緊急項目。舉例來說,如果某個遙控應用程式的使用者期望操作立即見效,您可以呼叫 setUrgent(),讓系統立即同步處理資料項目。

如果未呼叫 setUrgent(),系統最長可能會延遲 30 分鐘才同步處理非緊急的資料項目,不過通常都只會延遲幾分鐘。預設的緊急狀況是非緊急,因此如果需要保留舊版 Wear OS API 的立即同步處理行為,就必須使用 setUrgent()

監聽資料項目事件

如果資料層連線有一端變更了資料項目,請通知使用者連線另一端所有的任何變動。只要實作資料項目事件的事件監聽器即可達到此效果。

以下範例程式碼片段會在上述範例定義的計數值有變動時向應用程式發出通知:

Kotlin

private const val COUNT_KEY = "com.example.key.count"

class MainActivity : Activity(), DataClient.OnDataChangedListener {

    private var count = 0

    override fun onResume() {
        super.onResume()
        Wearable.getDataClient(this).addListener(this)
    }

    override fun onPause() {
        super.onPause()
        Wearable.getDataClient(this).removeListener(this)
    }

    override fun onDataChanged(dataEvents: DataEventBuffer) {
        dataEvents.forEach { event ->
            // DataItem changed
            if (event.type == DataEvent.TYPE_CHANGED) {
                event.dataItem.also { item ->
                    if (item.uri.path.compareTo("/count") == 0) {
                        DataMapItem.fromDataItem(item).dataMap.apply {
                            updateCount(getInt(COUNT_KEY))
                        }
                    }
                }
            } else if (event.type == DataEvent.TYPE_DELETED) {
                // DataItem deleted
            }
        }
    }

    // Method to update the count
    private fun updateCount(int: Int) { ... }
    ...
}

Java

public class MainActivity extends Activity implements DataClient.OnDataChangedListener {
    private static final String COUNT_KEY = "com.example.key.count";
    private int count = 0;

    @Override
    protected void onResume() {
        super.onResume();
        Wearable.getDataClient(this).addListener(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        Wearable.getDataClient(this).removeListener(this);
    }

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        for (DataEvent event : dataEvents) {
            if (event.getType() == DataEvent.TYPE_CHANGED) {
                // DataItem changed
                DataItem item = event.getDataItem();
                if (item.getUri().getPath().compareTo("/count") == 0) {
                    DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();
                    updateCount(dataMap.getInt(COUNT_KEY));
                }
            } else if (event.getType() == DataEvent.TYPE_DELETED) {
                // DataItem deleted
            }
        }
    }

    // Method to update the count
    private void updateCount(int c) { ... }
    ...
}

這個活動會實作 DataClient.OnDataChangedListener 介面。活動會將本身加入 onResume() 方法做為資料項目事件的事件監聽器,並移除 onPause() 方法內的事件監聽器。如要查看使用圖片、檢視模型和服務的實作方式,請參閱 DataLayer 範例應用程式。

您也可以把事件監聽器實作為服務。詳情請見「監聽資料層事件」相關說明。