Напишите дополнительный класс Parcelable для другого участка
У меня есть класс, реализующий интерфейс Parcelable
:
class A implements Parcelable {
}
У меня есть еще один класс B
, который содержит объект A
как переменную экземпляра. В writeToPacel
внутри класса B
я хочу записать объект B
в Parcel
:
class B implements Parcelable{
public void writeToParcel(Parcel dest, int flags) {
dest.write ???
}
}
Как я могу писать и читать?
Ответы
Ответ 1
class B implements Parcelable{
//lets assume you have A as a data member
A obj;
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(obj , flags);
}
}
если вы хотите его прочитать, используйте этот
obj = in.readParcelable(A.class.getClassLoader());
Ответ 2
Лучший способ справиться с этим, что позволяет избежать рефлексии, - просто вызвать статического создателя в целевом типе следующим образом:
this.amazingObject = AmazingObject.CREATOR.createFromParcel(in);
и записать его в Parcelable
, используя this.amazingObject.writeToParcel(Parcel, int)
Внутренне, при вызове readParcelable(ClassLoader)
это происходит:
public final <T extends Parcelable> T readParcelable(ClassLoader loader) {
Parcelable.Creator<T> creator = readParcelableCreator(loader);
if (creator == null) {
return null;
}
if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
return ((Parcelable.ClassLoaderCreator<T>)creator).createFromParcel(this, loader);
}
return creator.createFromParcel(this);
}
Как вы можете видеть, последний вызов этого метода просто вызывает правый Creator
, но внутри readParcelableCreator
есть много отражения, которое можно избежать, просто называя его напрямую.
Эта утилита может быть полезна:
import android.os.Parcel;
import android.os.Parcelable;
public class Parcels {
public static void writeBoolean(Parcel dest, Boolean value) {
dest.writeByte((byte) (value != null && value ? 1 : 0));
}
public static Boolean readBoolean(Parcel in){
return in.readByte() != 0;
}
public static void writeParcelable(Parcel dest, int flags, Parcelable parcelable) {
writeBoolean(dest, parcelable == null);
if (parcelable != null) {
parcelable.writeToParcel(dest, flags);
}
}
public static <T extends Parcelable> T readParcelable(Parcel in, Parcelable.Creator<T> creator) {
boolean isNull = readBoolean(in);
return isNull ? null : creator.createFromParcel(in);
}
}
Ответ 3
Строка:
obj = (A)in.readParcelable(A.class.getClassLoader());
должен измениться на:
obj = (A)in.readParcelable(B.class.getClassLoader());
Я столкнулся с одной и той же проблемой, и несколько поисков Google, многие веб-страницы или учебники подсказывают, что мы используем A.class.getClassLoader()
, потому что мы отсылаем A, но на самом деле это НЕПРАВИЛЬНО, потому что вы получите нулевое значение, мы должны использовать B.class.getClassLoader()
потому что codes are INSIDE class B
. Я просто не знал, почему, но он может получить правильный объект A таким образом.
Добро пожаловать, чтобы прокомментировать и подтвердить!