커스텀 객체를 Parcelable로 만들려면 어떻게해야합니까?


338

내 물건을 Parcelable로 만들려고합니다. 그러나 사용자 정의 객체가 있으며 해당 객체에는 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 10 배 사실,이 링크는 앞으로 더 이상 활성화되지 않기 때문에 답변을 편집하고 코드를 추가해야합니다.
소설

16
일반 문자열이 아닌 사용자 지정 개체를 전달하는 방법을 묻는 OP 누구나 일반 문자열을 전달할 수 있습니다. CUSTOM OBJECT로 사용자를 만드는 방법을 설명해 주시겠습니까?

LocalBroadcastManager를 사용하여 전송하는 경우 인코딩 / 디코딩 부분을 실제로 구현해야합니까? Parcelable을 구현하고 추가로 넣는 것으로 충분합니까?
JohnyTex

문자열을 연속적으로 쓰는 대신 문자열 배열을 사용하는 이유는 무엇입니까?
Quentin Roy

writeToParcel메소드 내부에 문자열 배열을 작성하는 동안 멤버의 순서가 중요합니까?
Prakhar Mohan Srivastava



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, Instant Run)로 훌륭하게 재생되거나 재생되지 않을 수 있습니다.

장점 :

  • 코드 생성 라이브러리는 상용구 소스 코드에서 저장됩니다.
  • 주석은 수업을 아름답게 만듭니다.

단점 :

  • 간단한 수업에 적합합니다. 복잡한 클래스를 소포로 만드는 것은 까다로울 수 있습니다.
  • 롬복과 AspectJ는 잘 어울리지 않습니다. [세부]
  • 내 경고를 참조하십시오.

Hrisey

경고!

Hrisey는 Java 8과 관련하여 알려진 문제가 있으므로 현재 Android 개발에 사용할 수 없습니다. # 1 심볼 오류를 찾을 수 없음 (JDK 8)을 참조하십시오 .

Hrisey는 Lombok을 기반으로 합니다. Hrisey를 사용한 소포 가능 클래스 :

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

이제 Parcelable 인터페이스의 메소드를 구현할 필요가 없습니다. Hrisey는 전처리 단계에서 필요한 모든 코드를 생성합니다.

Gradle 종속성의 Hrisey :

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

지원되는 유형 은 여기참조하십시오 . 는 ArrayList그들 중 하나입니다.

IDE 용 플러그인 Hrisey xor Lombok *를 설치하고 놀라운 기능을 사용하십시오!

여기에 이미지 설명을 입력하십시오
* 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 종속성의 Parceler :

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

지원되는 속성 유형README 를 참조하십시오 .


자동 소포

AutoParcel 은 Parcelable Values ​​생성을 가능하게 하는 AutoValue 확장입니다.

주석이 달린 모델에 추가 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*/);
    }
}

Gradle 빌드 파일의 AutoParcel :

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 은 Kotlin 및 Java에 대해 형식이 안전한 Parcelable 상용구 코드를 자동으로 생성하는 주석 프로세서입니다. PaperParcel은 Kotlin Data Classes, AutoValue Extension을 통한 Google의 AutoValue 또는 일반 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;
    }

}

안드로이드-APT 안드로이드 스튜디오와 함께 주석 프로세서 작업에서 플러그인 도움을줍니다.


7

Parcelable 클래스 를 만드는 가장 간단한 방법을 찾았습니다.

여기에 이미지 설명을 입력하십시오


1
작은 데이터에는 적합하지만 복잡한 데이터를 가져 오면 작동하지 않습니다
Manohar Reddy

1

안드로이드 스튜디오에서 플러그인을 사용하여 객체를 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
무슨 플러그인을 의미합니까?
naXa

0

이제 Parceler 라이브러리를 사용 하여 사용자 정의 클래스를 소포로 변환 할 수 있습니다 . @Parcel으로 POJO 클래스에 주석을 달기 만하면 됩니다. 예 :

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

Example 클래스의 오브젝트를 작성하고 Parcel을 랩핑하고 인 텐트를 통해 번들로 보낼 수 있습니다. 예 :

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

이제 커스텀 클래스 객체를 얻으려면

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

0

안드로이드 parcable에는 몇 가지 독특한 것들이 있습니다. 그것들은 다음과 같습니다.

  1. 소포에 데이터를 넣는 순서와 동일하게 소포를 읽어야합니다.
  2. 소포를 읽은 후 소포가 비워집니다. 소포에 3 개의 데이터가있는 경우입니다. 그런 다음 3 번 읽은 후 소포가 비게됩니다.

예제 : Parceble 클래스를 만들려면 Parceble을 구현해야합니다. Percable에는 두 가지 방법이 있습니다.

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

Person 클래스가 있고 firstName, lastName 및 age라는 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우리는 Parcel에 데이터를 순서대로 쓰거나 추가합니다. 그런 다음 소포에서 데이터를 읽기위한 다음 코드를 추가해야합니다.

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 클래스는 소포를 작성하고 쓰는 동안 동일한 순서로 데이터를 가져옵니다.

이제 의도 getExtraputExtra코드가 다음 과 같이 나타납니다.

추가 :

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

Full 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

Android Studio에서 플러그인없이 Parcelable 클래스 만들기

클래스에서 Parcelable을 구현 한 다음 "구현 Parcelable"에 커서를 놓고 적중 Alt+Enter및 선택Add Parcelable implementation (이미지 참조). 그게 다야.

여기에 이미지 설명을 입력하십시오


-3

놓다: bundle.putSerializable("key",(Serializable) object);

얻을 : List<Object> obj = (List<Object>)((Serializable)bundle.getSerializable("key"));


3
이것은 ClassCastExceptionobject가 구현하지 않으면 발생합니다 Serializable.
naXa

1
이 코드 스 니펫은 문제를 해결할 수 있지만 설명을 포함하면 게시물의 품질을 향상시키는 데 실제로 도움이됩니다. 앞으로 독자에게 질문에 대한 답변을 제공하고 있으며 해당 사람들이 코드 제안의 이유를 모를 수도 있습니다. 설명 주석으로 코드를 복잡하게 만들지 마십시오. 코드와 설명의 가독성이 떨어집니다!
Ashish Ahuja 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.