ฉันจะทำให้วัตถุที่กำหนดเองของฉันพัสดุได้อย่างไร


338

ฉันพยายามที่จะทำให้วัตถุของฉันพัสดุได้ อย่างไรก็ตามฉันมีวัตถุที่กำหนดเองและวัตถุเหล่านั้นมีArrayListคุณสมบัติของวัตถุที่กำหนดเองอื่น ๆ ที่ฉันทำ

อะไรจะเป็นวิธีที่ดีที่สุดในการทำสิ่งนี้?

คำตอบ:


432

คุณสามารถค้นหาตัวอย่างบางส่วนของเรื่องนี้ที่นี่ , ที่นี่ (รหัสถูกนำมาที่นี่)และที่นี่

คุณสามารถสร้างชั้น POJO นี้ Parcelableแต่คุณจะต้องเพิ่มรหัสพิเศษบางอย่างที่จะทำให้มัน ลองดูที่การนำไปปฏิบัติ

public class Student implements Parcelable{
        private String id;
        private String name;
        private String grade;

        // Constructor
        public Student(String id, String name, String grade){
            this.id = id;
            this.name = name;
            this.grade = grade;
       }
       // Getter and setter methods
       .........
       .........

       // Parcelling part
       public Student(Parcel in){
           String[] data = new String[3];

           in.readStringArray(data);
           // the order needs to be the same as in writeToParcel() method
           this.id = data[0];
           this.name = data[1];
           this.grade = data[2];
       }

       verride
       public int describeContents(){
           return 0;
       }

       @Override
       public void writeToParcel(Parcel dest, int flags) {
           dest.writeStringArray(new String[] {this.id,
                                               this.name,
                                               this.grade});
       }
       public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
           public Student createFromParcel(Parcel in) {
               return new Student(in); 
           }

           public Student[] newArray(int size) {
               return new Student[size];
           }
       };
   }

เมื่อคุณสร้างคลาสนี้คุณสามารถผ่านวัตถุของคลาสนี้ผ่านสิ่งIntentนี้ได้อย่างง่ายดายและกู้คืนวัตถุนี้ในกิจกรรมเป้าหมาย

intent.putExtra("student", new Student("1","Mike","6"));

ที่นี่นักเรียนเป็นกุญแจสำคัญที่คุณจะต้องยกเลิกการรวบรวมข้อมูลจากชุดข้อมูล

Bundle data = getIntent().getExtras();
Student student = (Student) data.getParcelable("student");

ตัวอย่างนี้แสดงเฉพาะStringประเภท แต่คุณสามารถจัดเก็บข้อมูลประเภทใดก็ได้ที่คุณต้องการ ลองดู

แก้ไข: อีกตัวอย่าง , แนะนำโดยRukmal Dias


@Rukmal Dias 10x อันที่จริงฉันต้องแก้ไขคำตอบและเพิ่มรหัสเพราะลิงก์เหล่านี้จะไม่ทำงานอีกต่อไปในอนาคต
นิยาย

16
OP ถามวิธีส่งผ่านวัตถุที่กำหนดเองไม่ใช่สตริงปกติ ทุกคนสามารถผ่านสตริงปกติได้ คุณช่วยอธิบายวิธีสร้างด้วย CUSTOM OBJECT ได้อย่างไร

ฉันต้องใช้ส่วนการเข้ารหัส / ถอดรหัสจริง ๆ หรือไม่ถ้าฉันส่งเฉพาะพวกเขาโดยใช้ LocalBroadcastManager มันเพียงพอที่จะใช้ Parcelable และเพิ่มเป็นพิเศษหรือไม่
JohnyTex

เหตุใดคุณจึงใช้อาร์เรย์สตริงแทนการเขียนสตริงอย่างต่อเนื่อง
เควนตินรอย

ลำดับของสมาชิกในขณะที่สร้างอาร์เรย์สตริงภายในwriteToParcelเมธอดสำคัญหรือไม่
Prakhar Mohan Srivastava


113

IntelliJ IDEAและ Android Studio มีปลั๊กอินสำหรับสิ่งนี้:

ปลั๊กอินเหล่านี้สร้างโค้ดสำเร็จรูปสำเร็จรูปที่Android Parcelableขึ้นอยู่กับฟิลด์ในชั้นเรียน

การสาธิตปลั๊กอิน


วิธีใหม่ในการทำสิ่งนั้นดีมาก!
sud007

56

1. นำเข้า Android Parcelable code generator

ป้อนคำอธิบายรูปภาพที่นี่

2. สร้างคลาส

public class Sample {
    int id;
    String name;
}

3. สร้าง> พัสดุจากเมนู

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่

เสร็จสิ้น


7
สำหรับผู้ที่ไม่ทราบว่ากล่องโต้ตอบเรียกดูที่เก็บอยู่ที่: File > Settings... > Pluginsและคลิกที่Browse repositories...ปุ่ม
DaedalusAlpha

ขอบคุณมากช่วยมาก!
Strahinja Ajvaz

21

อย่างไร? ด้วยคำอธิบายประกอบ

คุณเพียงใส่คำอธิบายประกอบ POJO ด้วยคำอธิบายประกอบพิเศษและห้องสมุดทำหน้าที่ส่วนที่เหลือ

คำเตือน!

ฉันไม่แน่ใจว่า Hrisey, Lombok และไลบรารี่การสร้างโค้ดอื่น ๆ เข้ากันได้กับระบบบิลด์ใหม่ของ Android พวกเขาอาจหรือไม่อาจเล่นได้อย่างดีกับรหัสการแลกเปลี่ยนร้อน (เช่น jRebel เรียกใช้ทันที)

ข้อดี:

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

จุดด้อย:

  • มันทำงานได้ดีสำหรับคลาสที่เรียบง่าย การทำพัสดุในระดับซับซ้อนอาจยุ่งยาก
  • ลอมบอกและ AspectJ เล่นได้ไม่ดี [รายละเอียด]
  • ดูคำเตือนของฉัน

Hrisey

คำเตือน!

Hrisey มีปัญหาที่ทราบกับ Java 8 และดังนั้นจึงไม่สามารถใช้สำหรับการพัฒนา Android ในปัจจุบัน ดู# 1 ไม่สามารถหาข้อผิดพลาดสัญลักษณ์ (JDK 8)

Hrisey อยู่บนพื้นฐานของลอมบอก ระดับพัสดุโดยใช้Hrisey :

@hrisey.Parcelable
public final class POJOClass implements android.os.Parcelable {
    /* Fields, accessors, default constructor */
}

ตอนนี้คุณไม่จำเป็นต้องใช้วิธีการใด ๆ ของส่วนต่อประสาน Parcelable Hrisey จะสร้างรหัสที่จำเป็นทั้งหมดในช่วงการประมวลผลล่วงหน้า

Hrisey ในการพึ่งพา Gradle:

provided "pl.mg6.hrisey:hrisey:${hrisey.version}"

ดูที่นี่สำหรับประเภทที่รองรับ ArrayListเป็นหนึ่งในพวกเขา

ติดตั้งปลั๊กอิน - Hrisey xor Lombok * - สำหรับ IDE ของคุณและเริ่มใช้คุณสมบัติที่น่าทึ่ง!

ป้อนคำอธิบายรูปภาพที่นี่
* อย่าเปิดใช้งานปลั๊กอิน Hrisey และ Lombok ด้วยกันไม่เช่นนั้นคุณจะได้รับข้อผิดพลาดระหว่างการเปิดตัว IDE


Parceler

ระดับพัสดุโดยใช้พัสดุภัณฑ์ :

@java.org.parceler.Parcel
public class POJOClass {
    /* Fields, accessors, default constructor */
}

ในการใช้รหัสที่สร้างขึ้นคุณสามารถอ้างอิงคลาสที่สร้างขึ้นโดยตรงหรือParcelsใช้คลาสยูทิลิตี้

public static <T> Parcelable wrap(T input);

หากต้องการยกเลิกการอ้างอิงให้@ParcelเรียกวิธีการParcelsเรียนต่อไปนี้

public static <T> T unwrap(Parcelable input);

พัสดุภัณฑ์ในการพึ่งพา Gradle:

compile "org.parceler:parceler-api:${parceler.version}"
provided "org.parceler:parceler:${parceler.version}"

มองในREADMEสำหรับการสนับสนุนประเภทแอตทริบิวต์


AutoParcel

AutoParcelเป็นAutoValueส่วนขยายที่เปิดใช้งานการสร้างค่า Parcelable

เพียงเพิ่มโมเดลที่มีคำอธิบายประกอบimplements Parcelableของคุณ@AutoValue:

@AutoValue
abstract class POJOClass implements Parcelable {
    /* Note that the class is abstract */
    /* Abstract fields, abstract accessors */

    static POJOClass create(/*abstract fields*/) {
        return new AutoValue_POJOClass(/*abstract fields*/);
    }
}

AutoParcel ในไฟล์ build Gradle:

apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'

repositories {
    /*...*/
    maven {url "https://clojars.org/repo/"}
}

dependencies {
    apt "frankiesardo:auto-parcel:${autoparcel.version}"
}

PaperParcel

PaperParcelเป็นหน่วยประมวลผลคำอธิบายประกอบที่สร้างรหัสสำเร็จรูปสำเร็จรูปที่ปลอดภัยสำหรับ Parcelable สำหรับ Kotlin และ Java PaperParcel รองรับ Kotlin Data Classes, AutoValue ของ Google ผ่าน AutoValue Extension หรือเพียงแค่วัตถุ Java bean ปกติ

ตัวอย่างการใช้งานจากเอกสาร
อธิบายคลาสข้อมูลของคุณด้วย@PaperParcelใช้PaperParcelableและเพิ่มอินสแตนซ์ JVM แบบคงที่PaperParcelable.Creatorเช่น:

@PaperParcel
public final class Example extends PaperParcelable {
    public static final PaperParcelable.Creator<Example> CREATOR = new PaperParcelable.Creator<>(Example.class);

    private final int test;

    public Example(int test) {
        this.test = test;
    }

    public int getTest() {
        return test;
    }
}

สำหรับผู้ใช้ Kotlin ดูการใช้งาน Kotlin ; สำหรับผู้ใช้ AutoValue ดูการใช้งาน AutoValue


ParcelableGenerator

ParcelableGenerator (README ถูกเขียนเป็นภาษาจีนและฉันไม่เข้าใจเลยคำแนะนำนี้จากนักพัฒนาที่พูดภาษาอังกฤษเป็นภาษาจีนยินดีต้อนรับ)

ตัวอย่างการใช้งานจากREADME

import com.baoyz.pg.Parcelable;

@Parcelable
public class User {

    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}

หุ่นยนต์ฉลาดช่วยปลั๊กอินในการทำงานกับหน่วยประมวลผลคำอธิบายประกอบในการรวมกันกับ Android สตูดิโอ


7

ฉันพบวิธีที่ง่ายที่สุดในการสร้างคลาส Parcelable

ป้อนคำอธิบายรูปภาพที่นี่


1
มันทำงานได้ดีสำหรับข้อมูลขนาดเล็ก แต่ถ้าเรานำข้อมูลที่ซับซ้อนนี้ทำงานตามปกติ
มาโนฮาร์เรดดี้

1

มันง่ายมากคุณสามารถใช้ปลั๊กอินบน android studio เพื่อสร้างวัตถุพัสดุ

public class Persona implements Parcelable {
String nombre;
int edad;
Date fechaNacimiento;

public Persona(String nombre, int edad, Date fechaNacimiento) {
    this.nombre = nombre;
    this.edad = edad;
    this.fechaNacimiento = fechaNacimiento;
}

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(this.nombre);
    dest.writeInt(this.edad);
    dest.writeLong(fechaNacimiento != null ? fechaNacimiento.getTime() : -1);
}

protected Persona(Parcel in) {
    this.nombre = in.readString();
    this.edad = in.readInt();
    long tmpFechaNacimiento = in.readLong();
    this.fechaNacimiento = tmpFechaNacimiento == -1 ? null : new Date(tmpFechaNacimiento);
}

public static final Parcelable.Creator<Persona> CREATOR = new Parcelable.Creator<Persona>() {
    public Persona createFromParcel(Parcel source) {
        return new Persona(source);
    }

    public Persona[] newArray(int size) {
        return new Persona[size];
    }
};}

4
คุณหมายถึงปลั๊กอินอะไร?
naXa

0

ตอนนี้คุณสามารถใช้ไลบรารีParcelerเพื่อแปลงคลาสแบบกำหนดเองของคุณเป็น parcelable เพียงใส่คำอธิบายประกอบชั้น POJO ของคุณด้วย@Parcel เช่น

    @Parcel
    public class Example {
    String name;
    int id;

    public Example() {}

    public Example(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getName() { return name; }

    public int getId() { return id; }
}

คุณสามารถสร้างวัตถุของคลาสตัวอย่างและตัดผ่าน Parcels และส่งเป็นชุดรวมถึงเจตนา เช่น

Bundle bundle = new Bundle();
bundle.putParcelable("example", Parcels.wrap(example));

ตอนนี้เพื่อให้ได้คลาสวัตถุที่กำหนดเองใช้

Example example = Parcels.unwrap(getIntent().getParcelableExtra("example"));

0

Android parcable มีสิ่งที่ไม่ซ้ำกัน เหล่านั้นจะได้รับร้อง:

  1. คุณต้องอ่านพัสดุตามลำดับเดียวกับที่คุณใส่ข้อมูลลงในพัสดุ
  2. พัสดุจะว่างเปล่าหลังจากอ่านจากพัสดุ นั่นคือถ้าคุณมี 3 ข้อมูลในพัสดุของคุณ หลังจากอ่านพัสดุ 3 ครั้งจะว่างเปล่า

ตัวอย่าง: หากต้องการสร้างคลาส Parceble จะต้องใช้ Parceble สามารถตรวจได้ 2 วิธี:

int describeContents();
void writeToParcel(Parcel var1, int var2);

สมมติว่าคุณมีคลาสบุคคลและมี 3 ฟิลด์, ชื่อ, นามสกุลและอายุ หลังจากใช้งานอินเตอร์เฟส Parceble อินเทอร์เฟซนี้ได้รับการร้อง:

import android.os.Parcel;
import android.os.Parcelable;
public class Person implements Parcelable{
    private String firstName;
    private String lastName;
    private int age;

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(firstName);
        parcel.writeString(lastName);
        parcel.writeInt(age);
    }

}

writeToParcelวิธีการที่นี่เรากำลังเขียน / เพิ่มข้อมูลบนพัสดุในการสั่งซื้อ หลังจากนี้เราต้องเพิ่มรหัสร้องสำหรับอ่านข้อมูลจากพัสดุ:

protected Person(Parcel in) {
        firstName = in.readString();
        lastName = in.readString();
        age = in.readInt();
    }

    public static final Creator<Person> CREATOR = new Creator<Person>() {
        @Override
        public Person createFromParcel(Parcel in) {
            return new Person(in);
        }

        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };

ที่นี่คลาส Person กำลังรับพัสดุและรับข้อมูลในลำดับเดียวกันระหว่างการเขียน

ตอนนี้ในช่วงเจตนาgetExtraและputExtraรหัสจะได้รับร้อง:

ใส่พิเศษ :

Person person=new Person();
                person.setFirstName("First");
                person.setLastName("Name");
                person.setAge(30);

                Intent intent = new Intent(getApplicationContext(), SECOND_ACTIVITY.class);
                intent.putExtra()
                startActivity(intent); 

รับพิเศษ:

Person person=getIntent().getParcelableExtra("person");

คลาสบุคคลเต็มจะได้รับการร้อง :

import android.os.Parcel;
import android.os.Parcelable;

public class Person implements Parcelable{
    private String firstName;
    private String lastName;
    private int age;



    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(firstName);
        parcel.writeString(lastName);
        parcel.writeInt(age);
    }

    protected Person(Parcel in) {
        firstName = in.readString();
        lastName = in.readString();
        age = in.readInt();
    }

    public static final Creator<Person> CREATOR = new Creator<Person>() {
        @Override
        public Person createFromParcel(Parcel in) {
            return new Person(in);
        }

        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };

}

Hope this will help you 
Thanks :)

0

สร้างคลาส Parcelable โดยไม่มีปลั๊กอินใน Android Studio

ใช้ Parcelable ในชั้นเรียนของคุณแล้ววางเคอร์เซอร์ที่ "ใช้ Parcelable" แล้วกด Alt+EnterและเลือกAdd Parcelable implementation(ดูภาพ) แค่นั้นแหละ.

ป้อนคำอธิบายรูปภาพที่นี่


-3

ที่จะนำ: bundle.putSerializable("key",(Serializable) object);

ที่จะได้รับ: List<Object> obj = (List<Object>)((Serializable)bundle.getSerializable("key"));


3
ซึ่งจะนำไปสู่การถ้าวัตถุไม่ใช้ClassCastException Serializable
naXa

1
ในขณะที่ข้อมูลโค้ดนี้อาจแก้ไขคำถามรวมถึงคำอธิบายช่วยปรับปรุงคุณภาพของโพสต์ของคุณ จำไว้ว่าคุณกำลังตอบคำถามสำหรับผู้อ่านในอนาคตและคนเหล่านั้นอาจไม่ทราบสาเหตุของการแนะนำรหัสของคุณ โปรดอย่าพยายามทำให้รหัสของคุณแน่นเกินไปด้วยคำอธิบายที่อธิบายซึ่งจะช่วยลดความสามารถในการอ่านของทั้งรหัสและคำอธิบาย!
Ashish Ahuja
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.