Ответ 1
Решение в виде пучка:
В моем приложении я создал легкий класс, специально для отправки его с телефона для просмотра. Поскольку код разделяется между мобильными и носимыми частями приложения, его можно легко упаковать и восстановить на обоих устройствах без дублирования кода. Он обеспечивает Bundle
-подобный механизм, но использует DataMap
.
Пример реализации:
public class MyObject {
public final long itemId;
public final long sortOrder;
public final String priceString;
public MyObject(long itemId, long sortOrder, String priceString) {
this.itemId = itemId;
this.sortOrder = sortOrder;
this.priceString = priceString;
}
public MyObject(DataMap map) {
this(map.getLong("itemId"),
map.getLong("sortOrder"),
map.getString("priceString")
);
}
public DataMap putToDataMap(DataMap map) {
map.putLong("itemId", itemId);
map.putLong("sortOrder", sortOrder);
map.putString("priceString", priceString);
return map;
}
}
Написание такого класса позволит вам рассмотреть, что на самом деле нужно отправлять между устройствами для отправки как можно меньше. Он также не сломается, когда какое-либо поле будет добавлено или удалено (в противостоянии следующему решению).
Отвечая на ваши соображения:
Если вы не хотите писать новый класс и хотите повторно использовать существующий код, вы можете попробовать использовать приведенный ниже код. Это позволит вам оставаться с интерфейсом Parcelable
(без необходимости реализовывать интерфейс Serializable
). Я не тестировал его при отправке через устройства, но он добился успеха marshall()
и unmarshall()
массива байтов в/из Parcel и сохранил его в DataMap
.
ПРИМЕЧАНИЕ. Я не знаю точно, как Google Play Services сохраняет все эти данные DataApi
, но я боюсь, что что-то может сломаться, когда такой класс будет обновлен.
Например, класс будет обновлен на Android Wear, пользователь запустит приложение, которое попытается прочитать текущие данные из DataApi
(который был "сериализован" с использованием старой версии этого класса) и попытаться прочитать его из byte[]
как если бы это была обновленная версия. Эти проблемы должны быть проверены, но я не думаю, что они сделали так DataApi
"примитивным" только потому, что "или сделать сложнее разрабатывать приложения на Wear.
Я настоятельно рекомендую использовать Bundle
-подобное решение и не использовать решение Parcelable
.
Используйте это на свой страх и риск.
import android.os.Parcel;
import android.os.Parcelable;
import com.google.android.gms.wearable.DataMap;
/**
* <p>Allows to put and get {@link Parcelable} objects into {@link DataMap}</p>
* <b>USAGE:</b>
* <p>
* <b>Store object in DataMap:</b><br/>
* DataMapParcelableUtils.putParcelable(dataMap, "KEY", myParcelableObject);
* </p><p>
* <b>Restore object from DataMap:</b><br/>
* myParcelableObject = DataMapParcelableUtils.getParcelable(dataMap, "KEY", MyParcelableObject.CREATOR);
* </p>
* I do <b>not recommend</b> to use this method - it may fail when the class that implements {@link Parcelable} would be updated. Use it at your own risk.
* @author Maciej Ciemięga
*/
public class DataMapParcelableUtils {
public static void putParcelable(DataMap dataMap, String key, Parcelable parcelable) {
final Parcel parcel = Parcel.obtain();
parcelable.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
dataMap.putByteArray(key, parcel.marshall());
parcel.recycle();
}
public static <T> T getParcelable(DataMap dataMap, String key, Parcelable.Creator<T> creator) {
final byte[] byteArray = dataMap.getByteArray(key);
final Parcel parcel = Parcel.obtain();
parcel.unmarshall(byteArray, 0, byteArray.length);
parcel.setDataPosition(0);
final T object = creator.createFromParcel(parcel);
parcel.recycle();
return object;
}
}
Код также доступен на GitHub.