วิธีการอ่าน / เขียนบูลีนเมื่อใช้งานส่วนต่อประสาน Parcelable?


404

ฉันกำลังพยายามที่ArrayList Parcelableจะส่งรายการของวัตถุที่กำหนดเองให้กับกิจกรรม ฉันจะเริ่มต้นการเขียนmyObjectListระดับซึ่งทอดตัวและดำเนินการArrayList<myObject>Parcelable

คุณลักษณะบางส่วนของMyObjectมีbooleanแต่ไม่ได้มีวิธีการใดParcelread/writeBoolean

วิธีที่ดีที่สุดในการจัดการกับสิ่งนี้คืออะไร?


3
เพราะการอ่านทั้งหมดที่ฉันได้ทำเกี่ยวกับการส่งผ่านวัตถุระหว่างกิจกรรมทำให้การใช้งานของพัสดุเป็นแบบอนุกรมแทน
grunk

10
@MisterSquonk คุณไม่ควรใช้Serializableอินเทอร์เฟซสำหรับการสื่อสารระหว่างกิจกรรม มันช้า
Octavian A. Damiean

1
@grunk: ตกลงนั่นยุติธรรมพอ แต่จนกระทั่ง Intent.putExtra (ชื่อ String, ค่าที่สามารถทำให้เป็นอนุกรม) ได้ถูกทำเครื่องหมายว่าเลิกใช้แล้วในเอกสารฉันยินดีที่จะใช้มันต่อไปถ้ามันทำให้ชีวิตง่ายขึ้นสำหรับฉัน แค่ความคิด
Squonk

3
@ Octavian: แต่นั่นขึ้นอยู่กับการศึกษาต่อกรณีและมีความเกี่ยวข้อง
Squonk

2
ในความคิดเห็นของฉันทีมสถาปนิกของ android ขี้เกียจ !!! บูลีนอยู่ที่ไหน !!!!!!!!
Mateus

คำตอบ:


942

นี่คือวิธีที่ฉันทำมัน ...

writeToParcel:

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

readFromParcel:

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

38
ไม่มีเหตุผลที่จะใช้ byte มากกว่า int ไบต์มีความละเอียดมากขึ้นเนื่องจากการส่ง: dest.writeInt (myBoolean? 1: 0);
miguel

ทำไมความคิดเห็น @SiPlus ถึงมี upvotes มากมาย ทั้ง 1 หรือ 0 ไม่ "โหลด" เลย มันทำให้ไม่มีความแตกต่างอย่างแน่นอน และเมื่อใดที่ Java เป็นภาษาที่มีการพิมพ์น้อย
noone

13
@sotrh เขียนไบต์เพียงเขียน int:/** * Write a byte value into the parcel at the current dataPosition(), * growing dataCapacity() if needed. */ public final void writeByte(byte val) { writeInt(val); }
ดัลลัส

3
@Dallas เป็นสิ่งที่มาจากเอกสารหรือไม่ ถ้าเป็นเช่นนั้นไม่ต้องสนใจความคิดเห็นของฉัน ดูเหมือนว่าไม่เหมาะสมสำหรับ API ที่จะมีฟังก์ชั่นที่บอกว่าwriteByteแต่จริง ๆ แล้วเขียน int
sotrh

1
@sotrh ที่เป็น copy-paste จากซอร์สโค้ด เปิดแหล่ง android.os.Parcel และดูด้วยตัวคุณเอง
Yaroslav Mytkalyk

66

คุณสามารถใช้เมธอดwriteValueได้เช่นกัน ในความคิดของฉันนั่นเป็นทางออกที่ตรงไปตรงมาที่สุด

dst.writeValue( myBool );

หลังจากนั้นคุณสามารถเรียกดูได้ง่าย ๆ ด้วยการส่งแบบง่าย ๆ ไปที่Boolean:

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

ภายใต้ประทุน Android Framework จะจัดการเป็นจำนวนเต็ม:

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

แหล่งที่มาของ Androidแสดงส่วน "ภายใต้ประทุน" (ล. 1219) แม้ว่าจะมีประสิทธิภาพน้อยลงเล็กน้อย (เนื่องจากการเรียกใช้เมธอดและสวิตช์) วิธีนี้อ่านได้ง่ายขึ้นเล็กน้อย
desseim

6
รหัสตามที่เขียนไว้ที่นี่จะไม่รวบรวม readValue ต้องการ classloader แต่ไม่จำเป็นสำหรับ Booleans คุณควรอ่าน "boolean myBool = (Boolean) source.readValue (null);" ผู้ตรวจสอบที่ไม่รู้ว่ากำลังทำอะไรและปฏิเสธการแก้ไขคำตอบนี้: @hemang, jeeped, DavidRR
miguel

1
@miguel ที่จริงคงมัน :)
Taig

15

คุณประกาศเช่นนี้

 private boolean isSelectionRight;

เขียน

 out.writeInt(isSelectionRight ? 1 : 0);

อ่าน

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

ประเภทบูลีนจะต้องถูกแปลงเป็นสิ่งที่พัสดุสนับสนุนและเพื่อให้เราสามารถแปลงเป็น int ได้


ซึ่งทำให้เกิดข้อผิดพลาดชนิดที่เข้ากันไม่ได้ต้องพบบูลีน int หรือไม่
Paul Okeke

12

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

...

สิ่งนี้มีประโยชน์ :)
Dino Tw

8

ปกติแล้วฉันจะมีพวกมันในอาร์เรย์และโทรwriteBooleanArrayและreadBooleanArray

หากเป็นบูลีนเดี่ยวที่คุณต้องแพ็คคุณสามารถทำได้:

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

คุณเคยประสบปัญหาเมื่อคุณต้องการพัสดุแบบไม่กี่บูลีนหรือไม่ ... ฉันมี คุณช่วยฉันได้ไหม> stackoverflow.com/questions/13463727/… . ขอบคุณ
Roger Alien


5

ฉันแนะนำให้คุณใช้วิธีที่ง่ายที่สุดในการใช้งาน Parcelable หากคุณใช้ Android Studio

เพียงไปที่ไฟล์ -> การตั้งค่า -> ปลั๊กอิน -> เรียกดูพื้นที่เก็บข้อมูลและค้นหาพัสดุ. ดูภาพ

ป้อนคำอธิบายรูปภาพที่นี่ มันจะสร้างพัสดุโดยอัตโนมัติ

และมี webiste สำหรับการทำเช่นนี้ http://www.parcelabler.com/


4

ใช้งานสั้นและง่ายในKotlinด้วยการสนับสนุน nullable:

เพิ่มวิธีการในพัสดุ

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

@AliKazi คุณไม่สามารถทำได้ในคำสั่ง 1 บรรทัดใน Java พร้อมด้วยประเภทการสนับสนุนเพิ่มเติม คุณควรคงอยู่ 3 สถานะ ฉันคิดว่าคุณลืมโมฆะ
Pavel Shorokhov

@ comm1x, IDE ไม่ชอบวิธีนี้ `ไม่สามารถเข้าถึง" readBoolean "ก่อนที่จะเรียก superclass constructor
Adam Hurwitz

@ comm1x ฉันแก้ไขปัญหาได้แล้ว ในการทำงานวิธีการเพิ่มเติมจะต้องอยู่ในออบเจกต์ร่วม
Adam Hurwitz

3

คุณสามารถบรรจุค่าบูลีนลงในไบต์โดยใช้การปิดบังและการเปลี่ยน นั่นเป็นวิธีที่มีประสิทธิภาพที่สุดในการทำสิ่งนี้และอาจเป็นสิ่งที่พวกเขาคาดหวังให้คุณทำ


+1 จริงการประหยัดค่าเป็นไบต์จะมีประสิทธิภาพมากกว่า คุณจะช่วยฉันแก้ไขคำถามเพื่อเป็นตัวแทนความคิดของคุณได้ไหม
Octavian A. Damiean

คุณทำได้ แต่สิ่งที่คุณเขียนไม่ใช่สิ่งที่ฉันต้องการ มันจะทำงาน แต่ไม่ได้มีประสิทธิภาพมากที่สุด คุณสามารถแพ็ค 8 booleans ลงใน byte โดยใช้มาสก์และพีชคณิตแบบบูล
fleetway76

ในกรณีส่วนใหญ่ฉันเห็นด้วยกับคุณ แต่ฉันมีกรณีที่คลานขึ้นเป็นครั้งคราวที่ฉันต้องการสามสถานะที่บูลีนจะทำงานด้วย เช่นคำถามที่ตอบว่าใช่ / ไม่ใช่ ฉันต้องการ null เพื่อทราบว่าบูลีนมีการระบุไว้อย่างชัดเจนหรือไม่
ชาด Gorshing

ไม่มีเหตุผลที่ใช้ byte มากกว่า int เนื่องจากwriteByte()วิธีการของ Parcel โทรโดยตรงwriteInt()
Yaroslav Mytkalyk

3

ยากที่จะระบุคำถามจริงที่นี่ ฉันเดาว่าเป็นวิธีจัดการกับบูลีนเมื่อใช้Parcelableอินเทอร์เฟซ

คุณลักษณะบางอย่างของ MyObject เป็นบูลีน แต่พัสดุไม่มีวิธีการอ่าน / writeBoolean

คุณจะต้องเก็บค่าเป็นสตริงหรือเป็นไบต์ หากคุณไปหาสตริงคุณจะต้องใช้วิธีการคงที่ของStringคลาสที่เรียกว่าvalueOf()การแยกค่าบูลีน มันไม่ได้มีประสิทธิภาพเท่ากับการบันทึกในไบต์ที่ยากลำบาก

String.valueOf(theBoolean);

ถ้าคุณไปหาไบต์คุณจะต้องใช้ตรรกะการแปลงด้วยตัวคุณเอง

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

เมื่อไม่ทำการบ้านParcelวัตถุคุณต้องดูแลการแปลงให้เป็นแบบดั้งเดิม


ไม่มีเหตุผลที่จะใช้ String มีเหตุผลที่ใช้ไบต์กว่า int ไม่เป็นตั้งแต่พัสดุของวิธีการเรียกโดยตรงwriteByte() writeInt()ตรรกะการแปลงมากเกินไป เพียงทำwriteInt(boolean ? 1 : 0)และboolean = readInt() != 0
ยาโรสลาฟ Mytkalyk

1

คนอื่นได้ตอบคำถามนี้อย่างสมบูรณ์แบบถ้าคุณต้องการทำด้วยตัวเอง

หากคุณต้องการที่จะสรุปหรือซ่อนรหัสพัสดุส่วนใหญ่ในระดับต่ำคุณอาจลองใช้รหัสที่ฉันเขียนเมื่อไม่นานมานี้เพื่อลดความยุ่งยากในการจัดการพัสดุ

การเขียนพัสดุเป็นเรื่องง่ายเหมือน:

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

โดยที่ color เป็น enum และ isDriving เป็นบูลีนตัวอย่างเช่น

การอ่านจากพัสดุก็ไม่ยากเช่นกัน:

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

เพียงแค่ดูที่ "ParceldroidExample" ฉันเพิ่มลงในโครงการ

ในที่สุดมันก็ทำให้ CREATOR initializer สั้น:

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

.class.getClassLoader()ขอบคุณสำหรับ
CoolMind

0

มีตัวอย่างมากมายในแหล่ง Android (AOSP) ตัวอย่างเช่นPackageInfoคลาสมีสมาชิกบูลีนrequiredForAllUsersและมีการจัดลำดับดังนี้:

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

private PackageInfo(Parcel source) {
    ...
    requiredForAllUsers = source.readInt() != 0;
    ...
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.