开发者

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

开发者 https://www.devze.com 2023-03-10 03:41 出处:网络
I\'m trying to make an ArrayList Parcelable in order to pass to an activity a list of custom object. I start writing a myObjectList class which extends ArrayList<myObject> and implement Parcelab

I'm trying to make an ArrayList Parcelable in order to pass to an activity a list of custom object. I start writing a myObjectList class which extends ArrayList<myObject> and implement Parcelable.

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

What is the best way to handle this开发者_StackOverflow中文版?


Here's how I'd do it...

writeToParcel:

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

readFromParcel:

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


You could also make use of the writeValue method. In my opinion that's the most straightforward solution.

dst.writeValue( myBool );

Afterwards you can easily retrieve it with a simple cast to Boolean:

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

Under the hood the Android Framework will handle it as an integer:

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


you declare like this

 private boolean isSelectionRight;

write

 out.writeInt(isSelectionRight ? 1 : 0);

read

isSelectionRight  = in.readInt() != 0;

boolean type needs to be converted to something that Parcel supports and so we can convert it to int.


AndroidStudio (using 2.3 atm), after implementing Parcelable on your class, you can simply hold your mouse pointer over your class name and it asks you to add the parcelable implementation:

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

From the four fields, it generates the following:

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

...


I normally have them in an array and call writeBooleanArray and readBooleanArray

If it's a single boolean you need to pack, you could do this:

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


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


Short and simple implementation in Kotlin, with nullable support:

Add methods to 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
    }
}

And use it:

parcel.writeBoolean(isUserActive)

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


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

Simply go to File->Settings->Plugins->Browse Repository and search for parcelable .See image

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

It will automatically create Parcelable.

And there is a webiste also for doing this. http://www.parcelabler.com/


You could pack your boolean values into a byte using masking and shifting. That would be the most efficient way to do it and is probably what they would expect you to do.


It is hard to identify the real question here. I guess it is how to deal with booleans when implementing the Parcelable interface.

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

You will have to either store the value as a string or as a byte. If you go for a string then you'll have to use the static method of the String class called valueOf() to parse the boolean value. It isn't as effective as saving it in a byte tough.

String.valueOf(theBoolean);

If you go for a byte you'll have to implement a conversion logic yourself.

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

When unmarshalling the Parcel object you have to take care of the conversion to the original type.


This question has already been answered perfectly by other people, if you want to do it on your own.

If you prefer to encapsulate or hide away most of the low-level parceling code, you might consider using some of the code I wrote some time ago for simplifying handling of parcelables.

Writing to a parcel is as easy as:

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

where color is an enum and isDriving is a boolean, for example.

Reading from a parcel is also not much harder:

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

Just take a look at the "ParceldroidExample" I added to the project.

Finally, it also keeps the CREATOR initializer short:

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


There are many examples in the Android (AOSP) sources. For example, PackageInfo class has a boolean member requiredForAllUsers and it is serialized as follows:

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

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


For API 29 and above we can use

writeToParcel:

dest.writeBoolean(booleanFlag);

readFromParcel:

booleanFlag = in.readBoolean()

Or We can use

writeToParcel:

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

readFromParcel:

booleanFlag = in.readByte() != 0;


Since api 29, you can now use the readBoolean() in the Parcel class. see https://developer.android.com/reference/android/os/Parcel#readBoolean() for more

0

精彩评论

暂无评论...
验证码 换一张
取 消