Làm thế nào tôi có thể làm cho các đối tượng tùy chỉnh của mình Parcelable?


338

Tôi đang cố gắng để làm cho các đối tượng của tôi Parcelable. Tuy nhiên, tôi có các đối tượng tùy chỉnh và các đối tượng đó có ArrayListthuộc tính của các đối tượng tùy chỉnh khác mà tôi đã thực hiện.

cách nào tốt nhất để làm việc này?

Câu trả lời:


431

Bạn có thể tìm thấy một số ví dụ về điều này ở đây , ở đây (mã được lấy ở đây)ở đây .

Bạn có thể tạo một lớp POJO cho việc này, nhưng bạn cần thêm một số mã bổ sung để tạo nó Parcelable. Có một cái nhìn vào việc thực hiện.

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

Khi bạn đã tạo lớp này, bạn có thể dễ dàng chuyển các đối tượng của lớp này thông qua Intentnhư thế này và khôi phục đối tượng này trong hoạt động đích.

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

Ở đây, sinh viên là chìa khóa mà bạn sẽ yêu cầu hủy dữ liệu từ gói.

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

Ví dụ này chỉ hiển thị Stringcác loại. Nhưng, bạn có thể gửi bất kỳ loại dữ liệu nào bạn muốn. Hãy thử nó.

EDIT: Một ví dụ khác , được đề xuất bởi Rukmal Dias .


@Rukmal Dias 10 lần. Trên thực tế, tôi phải chỉnh sửa câu trả lời của mình và thêm một số mã, vì các liên kết này sẽ không còn hoạt động vào một ngày nào đó trong tương lai.
tiểu thuyết

16
OP hỏi làm thế nào để vượt qua các đối tượng tùy chỉnh không phải chuỗi thông thường. Bất cứ ai cũng có thể vượt qua các chuỗi thông thường. Bạn có thể giải thích CÁCH tạo nó với ĐỐI TƯỢNG

Tôi có phải thực sự triển khai các phần mã hóa / giải mã nếu tôi chỉ gửi chúng bằng LocalBroadcastManager không? Có đủ để thực hiện Parcelable và đặt thêm?
JohnyTex

Tại sao bạn sử dụng một chuỗi chuỗi thay vì chỉ viết các chuỗi liên tiếp?
Quentin Roy

Thứ tự của các thành viên trong khi tạo mảng chuỗi bên trong writeToParcelphương thức có quan trọng không?
Prakhar Mohan Srivastava



56

1. Nhập khẩu Android Parcelable code generator

nhập mô tả hình ảnh ở đây

2. Tạo một lớp

public class Sample {
    int id;
    String name;
}

3. Tạo> Parcelable từ menu

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

Làm xong.


7
Đối với những người không biết hộp thoại Duyệt kho lưu trữ ở đâu: File > Settings... > Pluginsvà nhấp vào Browse repositories...nút.
DaedalusAlpha

Cảm ơn bạn, đã giúp đỡ rất nhiều!
Strahinja Ajvaz

21

Làm sao? Với các chú thích.

Bạn chỉ cần chú thích một POJO với một chú thích đặc biệt và thư viện sẽ làm phần còn lại.

Cảnh báo!

Tôi không chắc chắn rằng Hrisey, Lombok và các thư viện tạo mã khác tương thích với hệ thống xây dựng mới của Android. Họ có thể hoặc không thể chơi độc đáo với mã hoán đổi nóng (ví dụ jRebel, Instant Run).

Ưu điểm:

  • Thư viện tạo mã giúp bạn tiết kiệm từ mã nguồn soạn sẵn.
  • Chú thích làm cho lớp học của bạn đẹp.

Nhược điểm:

  • Nó hoạt động tốt cho các lớp đơn giản. Làm cho một lớp phức tạp bưu kiện có thể là khó khăn.
  • Lombok và AspectJ không chơi tốt với nhau. [chi tiết]
  • Xem cảnh báo của tôi.

Hrisey

Cảnh báo!

Hrisey có một vấn đề đã biết với Java 8 và do đó không thể được sử dụng để phát triển Android hiện nay. Xem # 1 Không thể tìm thấy lỗi biểu tượng (JDK 8) .

Hrisey dựa trên Lombok . Lớp Parcelable sử dụng Hrisey :

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

Bây giờ bạn không cần phải thực hiện bất kỳ phương pháp nào của giao diện Parcelable. Hrisey sẽ tạo ra tất cả các mã cần thiết trong giai đoạn tiền xử lý.

Hrisey trong phụ thuộc Gradle:

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

Xem ở đây để biết các loại được hỗ trợ. Đây ArrayListlà một trong số họ.

Cài đặt plugin - Hrisey xor Lombok * - cho IDE của bạn và bắt đầu sử dụng các tính năng tuyệt vời của nó!

nhập mô tả hình ảnh ở đây
* Không bật các plugin Hrisey và Lombok với nhau hoặc bạn sẽ gặp lỗi trong khi khởi chạy IDE.


Bưu kiện

Lớp Parcelable sử dụng Parceler :

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

Để sử dụng mã được tạo, bạn có thể tham chiếu trực tiếp lớp được tạo hoặc thông qua Parcelslớp tiện ích bằng cách sử dụng

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

Để hủy đăng ký @Parcel, chỉ cần gọi phương thức sau của Parcelslớp

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

Parceler trong phụ thuộc Gradle:

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

Xem trong README cho các loại thuộc tính được hỗ trợ .


AutoParcel

AutoParcel là tiện ích mở rộng AutoValue cho phép tạo giá trị Parcelable.

Chỉ cần thêm implements Parcelablevào các @AutoValuemô hình chú thích của bạn :

@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 trong tập tin xây dựng 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 là một bộ xử lý chú thích tự động tạo mã soạn sẵn Parcelable an toàn loại cho Kotlin và Java. PaperParcel hỗ trợ các lớp dữ liệu Kotlin, AutoValue của Google thông qua tiện ích mở rộng AutoValue hoặc chỉ các đối tượng bean Java thông thường.

Ví dụ sử dụng từ tài liệu .
Chú thích lớp dữ liệu của bạn với @PaperParcel, thực hiện PaperParcelablevà thêm một cá thể tĩnh JVM, ví PaperParcelable.Creatordụ:

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

Đối với người dùng Kotlin, xem Sử dụng Kotlin ; Đối với người dùng AutoValue, xem Sử dụng AutoValue .


ParcelableGenerator

ParcelableGenerator (README được viết bằng tiếng Trung Quốc và tôi không hiểu điều đó. Đóng góp cho câu trả lời này từ các nhà phát triển nói tiếng Anh-Trung Quốc được chào đón)

Ví dụ sử dụng từ 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;
    }

}

Các android-apt hỗ trợ plugin trong làm việc với bộ vi xử lý chú thích trong sự kết hợp với Android Studio.


7

Tôi đã tìm thấy cách đơn giản nhất để tạo lớp Parcelable

nhập mô tả hình ảnh ở đây


1
nó hoạt động tốt với dữ liệu nhỏ, nhưng nếu chúng tôi lấy dữ liệu phức tạp thì nó sẽ không hoạt động
Manohar Reddy

1

Nó rất dễ dàng, bạn có thể sử dụng một plugin trên android studio để tạo các đối tượng Parcelables.

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
Bạn có ý nghĩa gì với plugin?
naXa

0

Bây giờ bạn có thể sử dụng thư viện Parceler để chuyển đổi bất kỳ lớp tùy chỉnh nào của bạn theo dạng bưu kiện. Chỉ cần chú thích lớp POJO của bạn với @Parcel . ví dụ

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

bạn có thể tạo một đối tượng của lớp Ví dụ và bọc qua các Bưu phẩm và gửi dưới dạng một gói thông qua ý định. ví dụ

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

Bây giờ để có được đối tượng Lớp tùy chỉnh, chỉ cần sử dụng

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

0

Android parcable có một số điều độc đáo. Những người được đưa ra dưới đây:

  1. Bạn phải đọc Parcel theo cùng một thứ tự nơi bạn đặt dữ liệu trên bưu kiện.
  2. Bưu kiện sẽ trống sau khi đọc từ bưu kiện. Đó là nếu bạn có 3 dữ liệu trên bưu kiện của bạn. Sau đó đọc xong 3 lần bưu kiện sẽ trống.

Ví dụ: Để tạo một Parceble lớp, nó phải được thực hiện Parceble. Percable có 2 phương thức:

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

Giả sử bạn có một lớp Người và nó có 3 trường, FirstName, LastName và age. Sau khi thực hiện giao diện Parceble. giao diện này được đưa ra dưới đây:

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

}

Ở đây writeToParcelphương pháp chúng tôi đang viết / thêm dữ liệu trên Parcel theo thứ tự. Sau này, chúng ta phải thêm mã dưới đây để đọc dữ liệu từ bưu kiện:

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

Ở đây, lớp Person đang lấy một bưu kiện và nhận dữ liệu theo cùng một thứ tự trong khi viết.

Bây giờ trong ý định getExtraputExtramã được đưa ra dưới đây:

Đặt thêm :

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

Nhận thêm:

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

Lớp Full Person được đưa ra dưới đây:

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

Tạo lớp Parcelable không có plugin trong Android Studio

thực hiện Parcelable trong lớp của bạn và sau đó đặt con trỏ vào "thực hiện Parcelable" và nhấn Alt+Entervà chọn Add Parcelable implementation(xem hình ảnh). đó là nó.

nhập mô tả hình ảnh ở đây


-3

Để đặt: bundle.putSerializable("key",(Serializable) object);

Để có được: List<Object> obj = (List<Object>)((Serializable)bundle.getSerializable("key"));


3
Điều này sẽ dẫn đến ClassCastExceptionnếu đối tượng không thực hiện Serializable.
naXa

1
Mặc dù đoạn mã này có thể giải quyết câu hỏi, bao gồm một lời giải thích thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho độc giả trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn. Xin vui lòng cố gắng không làm đông mã của bạn với các bình luận giải thích, điều này làm giảm khả năng đọc của cả mã và các giải thích!
Ashish Ahuja
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.