我试图使一个ArrayList Parcelable,以便传递给一个活动的自定义对象列表。我开始写一个myObjectList类,它扩展了ArrayList<myObject>并实现了Parcelable。
ArrayList
Parcelable
myObjectList
ArrayList<myObject>
MyObject的一些属性是boolean,但Parcel没有任何方法read/writeBoolean。
MyObject
boolean
Parcel
read/writeBoolean
最好的处理方法是什么?
您可以使用屏蔽和移位将布尔值打包到一个字节中。这是最有效的方法,也可能是他们希望你做的。
这里很难找出真正的问题。我猜是在实现Parcelable接口时如何处理布尔值。
MyObject的一些属性是布尔型的,但是Parcel没有任何读写布尔型的方法。
您必须将值存储为字符串或字节。如果你想要一个字符串,那么你必须使用名为valueOf()的String类的静态方法来解析布尔值。它不像保存在字节坚韧中那样有效。
valueOf()
String
String.valueOf(theBoolean);
如果你想要一个字节,你必须自己实现一个转换逻辑。
byte convBool = -1; if (theBoolean) { convBool = 1; } else { convBool = 0; }
在解组Parcel对象时,必须注意到原始类型的转换。
我通常将它们放在一个数组中,并调用writeBooleanArray和readBooleanArray
writeBooleanArray
readBooleanArray
如果你需要打包一个布尔值,你可以这样做:
parcel.writeBooleanArray(new boolean[] {myBool});
我是这么做的……
writeToParcel:
dest.writeByte((byte) (myBoolean ? 1 : 0)); //if myBoolean == true, byte == 1
readFromParcel:
myBoolean = in.readByte() != 0; //myBoolean == true if byte != 0
你也可以使用writeValue方法。在我看来,这是最直接的解决办法。
dst.writeValue( myBool );
之后,你可以通过简单地转换到Boolean来轻松地检索它:
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;
布尔类型需要转换为Parcel支持的东西,所以我们可以将它转换为int。
out.writeInt(mBool ? 1 : 0); //Write this.mBool =in.readInt()==1; //Read
这个问题已经被其他人完美地回答了,如果你想自己做的话。
如果你更喜欢封装或隐藏大部分低级打包代码,你可以考虑使用一些代码,我写了一段时间,以简化处理包裹。
给包裹写信很简单:
parcelValues(dest, name, maxSpeed, weight, wheels, color, isDriving);
例如,其中color是enum, isDriving是boolean。
从包裹中阅读也不难:
color = (CarColor)unparcelValue(CarColor.class.getClassLoader()); isDriving = (Boolean)unparcelValue();
看看我添加到项目中的“parceldroideexample”。
最后,它还使CREATOR初始化项保持简短:
public static final Parcelable.Creator<Car> CREATOR = Parceldroid.getCreatorForClass(Car.class);
如果你使用Android Studio,我建议你使用最简单的方法来实现Parcelable。
简单地去文件- >设置- >插件- >浏览存储库并搜索parcelable .见图片
它将自动创建Parcelable.
有一个网友也在做这件事。http://www.parcelabler.com/
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); } ...
在芬兰湾的科特林中简短而简单的实现,具有可空支持:
为Parcel添加方法
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
在Android (AOSP)源码中有很多这样的例子。例如,PackageInfo类有一个布尔成员requiredForAllUsers,它被序列化如下:
PackageInfo
requiredForAllUsers
public void writeToParcel(Parcel dest, int parcelableFlags) { ... dest.writeInt(requiredForAllUsers ? 1 : 0); ... } private PackageInfo(Parcel source) { ... requiredForAllUsers = source.readInt() != 0; ... }
对于API 29及以上,我们可以使用
dest.writeBoolean (booleanFlag);
booleanFlag = in.readBoolean()
或者我们可以用
dest.writeByte((byte) (booleanFlag ?1: 0));
booleanFlag = in.readByte() != 0;
readBoolean()