我试图使一个数组列表Parcelable,以便传递给一个活动的自定义对象列表。我开始写一个myObjectList类,它扩展了ArrayList<myObject>并实现了Parcelable。

MyObject的一些属性是布尔型的,但是Parcel没有任何读写布尔型的方法。

最好的处理方法是什么?


您可以使用屏蔽和移位将布尔值打包到一个字节中。这是最有效的方法,也可能是他们希望你做的。

这里很难找出真正的问题。我猜是在实现Parcelable接口时如何处理布尔值。

MyObject的一些属性是布尔型的,但是Parcel没有任何读写布尔型的方法。

您必须将值存储为字符串或字节。如果你想要一个字符串,那么你必须使用string类的静态方法valueOf()来解析布尔值。它不像保存在字节坚韧中那样有效。

String.valueOf(theBoolean);

如果你想要一个字节,你必须自己实现一个转换逻辑。

byte convBool = -1;
if (theBoolean) {
    convBool = 1;
} else {
    convBool = 0;
}

在解编组Parcel对象时,必须注意到原始类型的转换。

我通常把它们放在一个数组中,调用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 myBool = (Boolean) source.readValue( null );

实际上,Android框架会把它作为一个整数来处理:

writeInt( (Boolean) v ? 1 : 0 );

你这样声明

 private boolean isSelectionRight;

 out.writeInt(isSelectionRight ? 1 : 0);

read

isSelectionRight  = in.readInt() != 0;

布尔类型需要转换为Parcel支持的东西,所以我们可以将它转换为int。

out.writeInt(mBool ? 1 : 0); //Write
this.mBool =in.readInt()==1; //Read

这个问题已经被其他人完美地回答了,如果你想自己做的话。

如果您更喜欢封装或隐藏大部分低级的打包代码,那么您可以考虑使用我在不久前编写的一些代码来简化对parcelables的处理。

给包裹写信很简单:

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);
}

...

在Kotlin中简短而简单的实现,具有可空支持:

为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,它被序列化如下:

public void writeToParcel(Parcel dest, int parcelableFlags) {
    ...
    dest.writeInt(requiredForAllUsers ? 1 : 0);
    ...
}

private PackageInfo(Parcel source) {
    ...
    requiredForAllUsers = source.readInt() != 0;
    ...
}

对于API 29及以上,我们可以使用

writeToParcel:

dest writeBoolean (booleanFlag);

readFromParcel:

booleanFlag = in.readBoolean()

或者我们可以用

writeToParcel:

dest.writeByte((byte) (booleanFlag ?1: 0));

readFromParcel:

布尔标志 = in.readbyte() != 0;

从api 29开始,你现在可以在Parcel类中使用readBoolean()。 详见https://developer.android.com/reference/android/os/Parcel#readBoolean()