使用 Data Layer API 同步数据项

DataItem 会定义系统在手持式设备与穿戴式设备之间同步数据时使用的接口。DataItem 通常由下面几部分组成:

  • 负载:可通过数据设置的字节数组,您可以用于执行自己的对象序列化和反序列化。负载的大小上限为 100KB。
  • 路径:必须以正斜杠开头的唯一字符串,例如 "/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) { ... }
    ...
}

此 Activity 实现了 DataClient.OnDataChangedListener 接口。此 activity 会在 onResume() 方法中将自身添加为数据项事件的监听器,并在 onPause() 方法中移除该监听器。如需查看使用图像的实现、视图模型和 服务,请参阅 DataLayer 示例 应用。

您还能以服务的形式实现该监听器。如需了解详情,请参阅监听数据层事件