我试图使一个ArrayList
Parcelable
自定义对象列表传递给活动。我开始写一个myObjectList
扩展ArrayList<myObject>
和实现的类Parcelable
。
的某些属性MyObject
是,boolean
但Parcel
没有任何方法read/writeBoolean
。
处理此问题的最佳方法是什么?
Serializable
界面进行交互性通信。太慢了
我试图使一个ArrayList
Parcelable
自定义对象列表传递给活动。我开始写一个myObjectList
扩展ArrayList<myObject>
和实现的类Parcelable
。
的某些属性MyObject
是,boolean
但Parcel
没有任何方法read/writeBoolean
。
处理此问题的最佳方法是什么?
Serializable
界面进行交互性通信。太慢了
Answers:
这是我的做法...
writeToParcel:
dest.writeByte((byte) (myBoolean ? 1 : 0)); //if myBoolean == true, byte == 1
readFromParcel:
myBoolean = in.readByte() != 0; //myBoolean == true if byte != 0
/** * Write a byte value into the parcel at the current dataPosition(), * growing dataCapacity() if needed. */ public final void writeByte(byte val) { writeInt(val); }
writeByte
,但实际上写了一个int。
您也可以使用writeValue方法。我认为这是最直接的解决方案。
dst.writeValue( myBool );
之后,您可以通过简单的强制转换为轻松地检索它Boolean
:
boolean myBool = (Boolean) source.readValue( null );
在底层,Android框架会将其作为整数处理:
writeInt( (Boolean) v ? 1 : 0 );
你这样声明
private boolean isSelectionRight;
写
out.writeInt(isSelectionRight ? 1 : 0);
读
isSelectionRight = (in.readInt() == 0) ? false : true;
布尔类型需要转换为Parcel支持的格式,因此我们可以将其转换为int。
AndroidStudio(使用2.3 atm),在您的类上实现了Parcelable之后,您只需将鼠标指针悬停在您的类名称上,它会要求您添加parcelable实现:
它从这四个字段生成以下内容:
public class YourClass implements Parcelable{
String someString;
int someInt;
boolean someBoolean;
List<String> someList;
protected YourClass(Parcel in) {
someString = in.readString();
someInt = in.readInt();
someBoolean = in.readByte() != 0;
someList = in.createStringArrayList();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(someString);
dest.writeInt(someInt);
dest.writeByte((byte) (someBoolean ? 1 : 0));
dest.writeStringList(someList);
}
...
我通常让他们在一个数组和呼叫writeBooleanArray
和readBooleanArray
如果您需要打包一个布尔值,则可以执行以下操作:
parcel.writeBooleanArray(new boolean[] {myBool});
如果您使用的是Android Studio,我建议您实现Parcelable的最简单方法。
只需转到File-> Settings-> Plugins-> Browse Repository并搜索可打包文件。
也有一个网络管理员可以这样做。http://www.parcelabler.com/
Kotlin中的简短实现,可空支持:
向包裹添加方法
fun Parcel.writeBoolean(flag: Boolean?) {
when(flag) {
true -> writeInt(1)
false -> writeInt(0)
else -> writeInt(-1)
}
}
fun Parcel.readBoolean(): Boolean? {
return when(readInt()) {
1 -> true
0 -> false
else -> null
}
}
并使用它:
parcel.writeBoolean(isUserActive)
parcel.readBoolean() // For true, false, null
parcel.readBoolean()!! // For only true and false
您可以使用掩码和移位将布尔值打包为一个字节。那将是最有效的方法,并且可能是他们希望您这样做的方法。
writeByte()
方法直接调用writeInt()
在这里很难确定真正的问题。我想这是实现Parcelable
接口时如何处理布尔值的方法。
MyObject的某些属性是boolean,但是Parcel没有任何方法read / writeBoolean。
您将必须将值存储为字符串或字节。如果要查找字符串,则必须使用String
该类的静态方法valueOf()
来解析布尔值。它不如将其保存在一个字节内有效。
String.valueOf(theBoolean);
如果需要一个字节,则必须自己实现转换逻辑。
byte convBool = -1;
if (theBoolean) {
convBool = 1;
} else {
convBool = 0;
}
解组Parcel
对象时,必须注意转换为原始类型。
writeByte()
方法直接调用,因此没有理由使用byte over int writeInt()
。转换逻辑太冗长。只是做writeInt(boolean ? 1 : 0)
与boolean = readInt() != 0
如果您想自己做,其他人已经很好地回答了这个问题。
如果您希望封装或隐藏大多数低级包裹代码,则可以考虑使用我前一段时间编写的一些代码,以简化包裹的处理。
写包裹很容易:
parcelValues(dest, name, maxSpeed, weight, wheels, color, isDriving);
例如,其中color是一个枚举,而isDriving是一个布尔值。
从包裹中读取也不难:
color = (CarColor)unparcelValue(CarColor.class.getClassLoader());
isDriving = (Boolean)unparcelValue();
只需看看我添加到项目中的“ ParceldroidExample”即可。
最后,它还使CREATOR初始化程序简短:
public static final Parcelable.Creator<Car> CREATOR =
Parceldroid.getCreatorForClass(Car.class);
.class.getClassLoader()
。