关于android:实现Parcelable接口时如何读取/写入布尔值?

How to read/write a boolean when implementing the Parcelable interface?

我正在尝试制作ArrayList Parcelable,以便将自定义对象的列表传递给活动。 我开始编写一个myObjectList类,该类扩展了ArrayList并实现了Parcelable

MyObject的某些属性是boolean,但是Parcel没有任何方法read/writeBoolean

处理此问题的最佳方法是什么?


这是我的做法...

writeToParcel:

1
dest.writeByte((byte) (myBoolean ? 1 : 0));     //if myBoolean == true, byte == 1

readFromParcel:

1
myBoolean = in.readByte() != 0;     //myBoolean == true if byte != 0


您也可以使用writeValue方法。我认为这是最直接的解决方案。

1
dst.writeValue( myBool );

然后,您可以通过简单地强制转换为Boolean来检索它:

1
boolean myBool = (Boolean) source.readValue( null );

在底层,Android框架会将其作为整数处理:

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


你这样声明

1
 private boolean isSelectionRight;

1
 out.writeInt(isSelectionRight ? 1 : 0);

1
isSelectionRight  = (in.readInt() == 0) ? false : true;

布尔类型需要转换为Parcel支持的格式,因此我们可以将其转换为int。


AndroidStudio(使用2.3 atm),在您的类上实现了Parcelable之后,您只需将鼠标指针悬停在您的类名称上,它会要求您添加parcelable实现:

enter image description here

它从这四个字段生成以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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);
}

...


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

我通常将它们放在数组中,然后调用writeBooleanArrayreadBooleanArray

如果您需要打包一个布尔值,则可以执行以下操作:

1
parcel.writeBooleanArray(new boolean[] {myBool});


I suggested you the easiest way to implement Parcelable if you are using Android Studio.

只需转到File-> Settings-> Plugins-> Browse Repository并搜索可打包文件。

enter image description here
它将自动创建Parcelable。

并且有一个网络专家也可以这样做。 http://www.parcelabler.com/


Kotlin中的简短实现,可空支持:

向包裹添加方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
    }
}

并使用它:

1
2
3
4
parcel.writeBoolean(isUserActive)

parcel.readBoolean()        // For true, false, null
parcel.readBoolean()!!      // For only true and false


在这里很难确定真正的问题。我想这是实现Parcelable接口时如何处理布尔值的方法。

Some attributes of MyObject are boolean but Parcel don't have any method read/writeBoolean.

您将必须将值存储为字符串或字节。如果要查找字符串,则必须使用称为valueOf()String类的静态方法来解析布尔值。它不如将其保存在一个字节内有效。

1
String.valueOf(theBoolean);

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

1
2
3
4
5
6
byte convBool = -1;
if (theBoolean) {
    convBool = 1;
} else {
    convBool = 0;
}

解组Parcel对象时,必须注意转换为原始类型。


您可以使用掩码和移位将布尔值打包为一个字节。那将是最有效的方法,并且可能是他们希望您这样做的方法。


如果您想自己做,其他人已经很好地回答了这个问题。

如果您希望封装或隐藏大多数低级包裹代码,则可以考虑使用我前一段时间编写的一些代码,以简化包裹的处理。

写包裹很容易:

1
parcelValues(dest, name, maxSpeed, weight, wheels, color, isDriving);

例如,其中color是一个枚举,而isDriving是一个布尔值。

从包裹中读取也不难:

1
2
color = (CarColor)unparcelValue(CarColor.class.getClassLoader());
isDriving = (Boolean)unparcelValue();

只需看看我添加到项目中的" ParceldroidExample"即可。

最后,它还使CREATOR初始化程序简短:

1
2
public static final Parcelable.Creator<Car> CREATOR =
    Parceldroid.getCreatorForClass(Car.class);


Android(AOSP)源代码中有很多示例。例如,PackageInfo类具有布尔成员requiredForAllUsers,并且其序列化如下:

1
2
3
4
5
6
7
8
9
10
11
public void writeToParcel(Parcel dest, int parcelableFlags) {
    ...
    dest.writeInt(requiredForAllUsers ? 1 : 0);
    ...
}

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