一. 前言
背景
一开始笔者在研究数据发送与接收的时候,看到Wear数据类DataMap除了可以put基本类型外,还有个fromBundle方法来构建一个DataMap对象。所以一口气的将原本功能上的序列化对象传递过去,结果手表端一直都收不到消息。
问题原因
后来查阅了开发者文档,发现这个Bundle并没有我们在Intent中传递数据的那么强大,它并不支持序列化!先附上开发者文档的说明:
Returns a DataMap from a Bundle. The input Bundle is expected to contain only elements supported by DataMap. Any elements in the Bundle not supported by DataMap will be dropped.
关键的一句是"The input Bundle is expected to contain only elements supported by DataMap",只有DataMap本身支持的类型才能被传递到Bundle中,那么也就是说我们自己构建的数据Bean并不能够直接序列化传进Bundle中,这导致结果是"Any elements in the Bundle not supported by DataMap will be dropped",即这些数据不会被传递,而是会被抛弃。
问题来了
那么,问题来了!怎么样才能够优雅地传递数据Bean呢?
接下来笔者将给出自己的解决方案。二. 解决方案
1. 使用公共工程
- 创建公共工程:因为数据在Phone工程和Wear工程是共用,为了避免在这两个工程中都各自持有数据类,最好的方式自然是将这部分抽出来。创建完毕后,打钩"Is Library",将公共工程设置为库工程。
- 导入公共工程:Phone工程和Wear工程都引用公共工程。
-
公共工程模板:以下用一个城市数据作为样例。注意:要使用DataMap这个类,必须引用5.0版本以上的GooglePlayServices。
import com.google.android.gms.wearable.DataMap;public class WearCityBean {public static final String KEY = "/bean/wear/city";private static final String M_CITY_ID = "mCityId";private static final String M_CITY_NAME = "mCityName";private static final String M_COUNTRY_NAME = "mCountryName";// 城市IDprivate String mCityId;// 城市名private String mCityName;// 国家名private String mCountryName;public WearCityBean() {}public WearCityBean(DataMap map) { setCityId(map.getString(M_CITY_ID)); setCityName(map.getString(M_CITY_NAME)); setCountryName(map.getString(M_COUNTRY_NAME));}public DataMap getDataMap() { DataMap map = new DataMap(); map.putString(M_CITY_ID, mCityId); map.putString(M_CITY_NAME, mCityName); map.putString(M_COUNTRY_NAME, mCountryName); return map;}public String getCityId() { return mCityId;}public void setCityId(String cityId) { mCityId = cityId;}public String getCityName() { return mCityName;}public void setCityName(String cityName) { mCityName = cityName;}public String getCountryName() { return mCountryName;}public void setCountryName(String countryName) { mCountryName = countryName;}@Overridepublic String toString() { return "WearCityBean [mCityId=" + mCityId + ", mCityName=" + mCityName + ", mCountryName=" + mCountryName + "]";}}
关键代码分析 - 发送数据:要发送数据的一端,将一个DataMap对象传入到这个方法中,将Bean自身的基本数据传递到DataMap中。这样,要发送数据的那一端就不用存在很多零散的代码,而且如果Phone端和Wear端都要实现数据发送的话,就不用重复两份代码了。
public DataMap getDataMap() { DataMap map = new DataMap(); map.putString(M_CITY_ID, mCityId); map.putString(M_CITY_NAME, mCityName); map.putString(M_COUNTRY_NAME, mCountryName); return map;}
发送端代码:下面通过先初始化一个WearCityBean对象后,再从中获取DataMap对象,最后再放到数据请求对象PutDataMapRequest中,完成发送的封装。
private void packageCityData(PutDataMapRequest dataMap) {//通过getWearCityBean()构建并初始化数据对象WearCityBean wearCityBean = getWearCityBean();DataMap map = wearCityBean.getDataMap();dataMap.getDataMap().putDataMap(WearCityBean.KEY, map);}
关键代码分析 - 接收数据:将收到的DataMap用来构建一个WearCityBean对象,即可完成数据的解析。
public WearCityBean(DataMap map) { setCityId(map.getString(M_CITY_ID)); setCityName(map.getString(M_CITY_NAME)); setCountryName(map.getString(M_COUNTRY_NAME));}
-
接收端的代码过于简单,就不再附上了。
后话
- 以上是笔者在API不够满足需求的情况下想出的一套解决方案,经过多次测试,运行良好。
- 除了直接的将基本数据类型传入DataMap中之外,还可以用Json或者其他方式将数据封装成一个String,再传入到DataMap中。这也是一个不错的方案。