lightbulb_outline Please take our October 2018 developer survey. Start survey

同步数据项

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

  • 负载 - 一个字节数组,您可以随意使用任何数据进行设置,让您可以执行自己的对象序列化和反序列化。负载的大小上限为 100KB。
  • 路径 - 必须以正斜杠开头的唯一字符串(例如,"/path/to/data"

:Wear 应用可以使用 Data Layer API 与手机应用通信,但不建议使用此 API 连接网络

您通常不需要直接实现 DataItem,而是执行以下操作:

  1. 创建一个 PutDataRequest 对象,指定一个可唯一识别该数据项的字符串路径。
  2. 调用 setData() 以设置负载。
  3. 如果同步延迟会对用户体验造成不良影响,则调用 setUrgent()
  4. 调用 DataApi.putDataItem() 以请求系统创建该数据项。

请求数据项时,系统会返回可正确实现 DataItem 接口的对象。不过,我们建议您不要使用 setData() 处理原始字节,而是使用数据图,后者在易用的类 Bundle 接口中公开数据项。

与数据图同步数据

如有可能,使用 DataMap 类。此方法允许您以 Android Bundle 形式处理数据项,以便系统为您执行对象序列化和反序列化,您就可以处理包含键-值对的数据。

要使用数据图,请执行以下操作:

  1. 创建一个 PutDataMapRequest 对象,设置数据项的路径。

    :路径字符串是数据项的唯一标识符,允许您从连接的任一端访问它。路径必须以正斜杠开头。如果您在应用中使用的是层级数据,应该创建一个与数据结构匹配的路径架构。

  2. 调用 PutDataMapRequest.getDataMap() 以获得可在其上设置值的数据图。
  3. 使用 put...() 函数(例如 putString())为数据图设置任何需要的值。
  4. 如果同步延迟会对用户体验造成不良影响,则调用 setUrgent()
  5. 调用 PutDataMapRequest.asPutDataRequest() 以获得 PutDataRequest 对象。
  6. 调用 DataApi.putDataItem() 以请求系统创建该数据项。

    :如果手持式设备和穿戴式设备连接中断,数据将进入缓冲区,并在连接重新建立时进行同步。

下例中的 increaseCounter() 函数显示如何创建数据图和在其中放入数据:

public class MainActivity extends Activity implements
        DataApi.DataListener,
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener {

    private static final String COUNT_KEY = "com.example.key.count";

    private GoogleApiClient mGoogleApiClient;
    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();
        PendingResult<DataApi.DataItemResult> pendingResult =
                Wearable.DataApi.putDataItem(mGoogleApiClient, putDataReq);
    }

    ...
}

如需了解有关处理 PendingResult 对象的详细信息,请参阅等待数据层调用的状态

设置 DataItem 优先级

Google Play 服务 8.3 及更高版本中,DataApi 接口允许紧急请求同步 DataItems。通常,系统可能会延迟向 Wear 网络传递 DataItems,以延长用户设备的电池续航时间,但如果延迟同步 DataItems 会给用户体验造成不良影响,您可以将它们标记为紧急。例如,用户期望其操作立即产生效果的遥控应用中,您可以通过调用 setUrgent() 让系统立即同步您的 DataItems

如果您不调用 setUrgent(),系统可能延迟长达 30 分钟后再同步非紧急 DataItems,但通常可以预计的是,即便有延迟,也只有几分钟。现在默认紧急程度为非紧急,因此如果您想保留旧版本 Wear API 中存在的立即同步行为,您必须使用 setUrgent()

侦听数据项 Event

如果数据层连接的一端更改了数据项,您可能希望在连接的另一端发生任何变化时收到通知。您可以通过实现数据项 event 侦听器来实现这一目的。

下例中的代码片段会在上一示例中定义的计数器值发生变化时通知您的应用:

public class MainActivity extends Activity implements
        DataApi.DataListener,
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener {

    private static final String COUNT_KEY = "com.example.key.count";

    private GoogleApiClient mGoogleApiClient;
    private int count = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(Wearable.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
    }

    @Override
    protected void onResume() {
        super.onResume();
        mGoogleApiClient.connect();
    }

    @Override
    public void onConnected(Bundle bundle) {
        Wearable.DataApi.addListener(mGoogleApiClient, this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        Wearable.DataApi.removeListener(mGoogleApiClient, this);
        mGoogleApiClient.disconnect();
    }

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

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

    ...
}

此 Activity 实现的是 DataItem.DataListener 接口。此 Activity 将自己作为数据项 event 侦听器添加到 onConnected() 函数内,并移除 onPause() 函数中的侦听器。

您还可以 service 形式实现侦听器。如需了解详细信息,请参阅侦听数据层 Event