gpt4 book ai didi

android - 在 fragment 中,恢复一个对象,该对象包含另一个具有 Parcelable 实现的对象的列表

转载 作者:行者123 更新时间:2023-11-30 05:08:57 27 4
gpt4 key购买 nike

我有一个 Car 类实现 Parcelable:

public class Car implements Parcelable {
private long id;
private String model;

public Car(long id, String model) {
this.id = id;
this.model = model;
}

public String getModel() {
return model;
}

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(this.id);
dest.writeString(this.model);

}

private Car(Parcel in) {
this.id = in.readLong();
this.model = in.readString();
}

public static final Creator<Car> CREATOR = new Creator<Car>() {
@Override
public Car createFromParcel(Parcel source) {
return new Car(source);
}

@Override
public Car[] newArray(int size) {
return new Car[size];
}
};
}

然后,我有一个包含汽车列表的Store类,它还实现了Parcelable:

public class Store implements Parcelable {
private List<Car> carList = new ArrayList<>();

public List<Car> getCarList() {
return carList;
}
public void setCarList(List<Car> cars) {
carList = cars;
}

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedList(this.carList);
}

private Store(Parcel in) {
in.readTypedList(carList, Car.CREATOR);
}

public static final Creator<Store> CREATOR = new Creator<Store>() {
@Override
public Store createFromParcel(Parcel source) {
return new Store(source);
}

@Override
public Store[] newArray(int size) {
return new Store[size];
}
};
}

在 fragment 中,我尝试恢复名为 myStoreStore 实例,包括其中的汽车列表:

class MyFragment extends Fragment {
private Store myStore;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null && savedInstanceState.containsKey(MY_STORE)) {
myStore = savedInstanceState.getParcelable(MY_STORE);
// PROBLEM IS HERE:
// when runtime hit here, the restored myStore contains one car but has id with weird long value and null in model field. WHY?
} else {
// initialize myStore with car list (only one car)
Car myCar = new Car(1, "BMW X1");
List<Car> cars = new ArrayList<>();
cars.add(myCar);

myStore = new Store();
myStore.setCarList(cars);
}
}

@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
if(myStore != null) {
outState.putParcelable(MY_STORE, myStore);
}
super.onSaveInstanceState(outState);
}

}

问题发生在 MyFragment 中,代码试图在 onCreate() 中恢复 myStore。在运行时,恢复的 myStore 确实包含列表中的一辆汽车,但该列表中的汽车具有奇怪的 long 值(例如 28429333427126393)和 nullmodel 字段中。为什么?我做错了什么?如何恢复一个对象包含另一个对象的列表?

最佳答案

此问题通常发生在您的 carList 时。 instance 为 null 所以你在 parcelable 中写了一个 null 对象并尝试从中读取。

其中一个选项是当列表为空时初始化列表,然后将其写入 parcelable。使用这种情况,您的列表在恢复后将始终有一个引用,这可能不是您要找的。

另一种方法是在将列表写入 parcelable 之前写入一个字节值,表明您的列表为空,或者您应该期望从中获得一些值。对于这种情况,我使用 this helper class这解决了我自己的问题。根据我的需要,我做了一些改进。如果您愿意使用,这是我的版本:

public class ParcelableUtils {
public static void write(Parcel dest, String string) {
dest.writeByte((byte) (string == null ? 0 : 1));
if (string != null) {
dest.writeString(string);
}
}

public static String readString(Parcel source) {
if (source.readByte() == 1) {
return source.readString();
}
return null;
}

public static void write(Parcel dest, Parcelable parcelable, int flags) {
dest.writeByte((byte) (parcelable == null ? 0 : 1));
if (parcelable != null) {
dest.writeParcelable(parcelable, flags);
}
}

public static <T extends Parcelable> T readParcelable(Parcel source) {
if (source.readByte() == 1) {
return source.readParcelable(null);
}
return null;
}

public static <T extends Parcelable> T readParcelable(Parcel source, Class objectClass) {
if (source.readByte() == 1) {
return source.readParcelable(objectClass.getClassLoader());
}
return null;
}

public static void write(Parcel dest, Map<String, String> strings) {
if (strings == null) {
dest.writeInt(-1);
}
{
dest.writeInt(strings.keySet().size());
for (String key : strings.keySet()) {
dest.writeString(key);
dest.writeString(strings.get(key));
}
}
}

public static Map<String, String> readStringMap(Parcel source) {
int numKeys = source.readInt();
if (numKeys == -1) {
return null;
}
HashMap<String, String> map = new HashMap<String, String>();
for (int i = 0; i < numKeys; i++) {
String key = source.readString();
String value = source.readString();
map.put(key, value);
}
return map;
}

public static <T extends Parcelable> void write(Parcel dest, Map<String, T> objects, int flags) {
if (objects == null) {
dest.writeInt(-1);
} else {
dest.writeInt(objects.keySet().size());
for (String key : objects.keySet()) {
dest.writeString(key);
dest.writeParcelable(objects.get(key), flags);
}
}
}

public static <T extends Parcelable> Map<String, T> readParcelableMap(Parcel source) {
int numKeys = source.readInt();
if (numKeys == -1) {
return null;
}
HashMap<String, T> map = new HashMap<String, T>();
for (int i = 0; i < numKeys; i++) {
String key = source.readString();
T value = source.readParcelable(null);
map.put(key, value);
}
return map;
}

public static void write(Parcel dest, URL url) {
dest.writeString(url.toExternalForm());
}

public static URL readURL(Parcel source) {
try {
return new URL(source.readString());
} catch (MalformedURLException e) {
e.printStackTrace();
}
return null;
}

public static void write(Parcel dest, Date date) {
dest.writeByte((byte) (date == null ? 0 : 1));
if (date != null) {
dest.writeLong(date.getTime());
}
}

public static Date readDate(Parcel source) {
if (source.readByte() == 1) {
return new Date(source.readLong());
}
return null;
}

public static <T extends java.lang.Enum<T>> void write(Parcel dest, java.lang.Enum<T> enu) {
if (enu == null) {
dest.writeString("");
} else {
dest.writeString(enu.name());
}
}

public static <T extends java.lang.Enum<T>> T readEnum(Parcel dest, Class<T> clazz) {
String name = dest.readString();
if ("".equals(name)) {
return null;
}
return java.lang.Enum.valueOf(clazz, name);
}

public static void write(Parcel dest, boolean bool) {
dest.writeByte((byte) (bool ? 1 : 0));
}

public static boolean readBoolean(Parcel source) {
return source.readByte() == 1;
}

public static <T extends Parcelable> void write(Parcel dest,
List<T> fields, int flags) {
if (fields == null) {
dest.writeInt(-1);
} else {
dest.writeInt(fields.size());
for (T field : fields) {
dest.writeParcelable(field, flags);
}
}
}

@SuppressWarnings("unchecked")
public static <T extends Parcelable> List<T> readParcelableList(
Parcel source) {
int size = source.readInt();
if (size == -1) {
return null;
}
ArrayList<T> list = new ArrayList<T>();
for (int i = 0; i < size; i++) {
list.add((T) source.readParcelable(null));
}
return list;
}
}

希望对您有所帮助。

关于android - 在 fragment 中,恢复一个对象,该对象包含另一个具有 Parcelable 实现的对象的列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54026032/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com