Как я могу сделать свои собственные объекты Parcelable?


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
ОП спрашивает, как передать пользовательские объекты, а не обычную строку. Любой может передать обычные строки. Не могли бы вы объяснить, как создать его с CUSTOM OBJECT

Должен ли я на самом деле реализовать части кодирования / декодирования, если я отправляю их только с помощью LocalBroadcastManager? Достаточно ли реализовать Parcelable и поставить как лишнее?
JohnyTex

Почему вы используете строковый массив вместо простого последовательного написания строк?
Квентин Рой

Имеет ли значение порядок членов при создании массива строк внутри writeToParcelметода?
Прахар Мохан Шривастава


113

IntelliJ IDEA и Android Studio имеют плагины для этого:

Эти плагины генерируют стандартный шаблон Android Parcelable на основе полей в классе.

Плагин демо


Пока новый способ сделать это, Ницца!
sud007

56

1. Импорт Android Parcelable code generator

введите описание изображения здесь

2. Создать класс

public class Sample {
    int id;
    String name;
}

3. Создать> Parcelable из меню

введите описание изображения здесь введите описание изображения здесь

Готово.


7
Для тех, кто не знает, где находится диалоговое окно «Обзор репозиториев»: File > Settings... > Pluginsнажмите Browse repositories...кнопку.
DaedalusAlpha

Спасибо, очень помогло!
Страхиня Айваз

21

Как? С аннотациями.

Вы просто аннотируете POJO специальной аннотацией, а библиотека делает все остальное.

Предупреждение!

Я не уверен, что Hrisey, Lombok и другие библиотеки генерации кода совместимы с новой системой сборки Android. Они могут или не могут хорошо играть с кодом горячей замены (например, jRebel, Instant Run).

Плюсы:

  • Библиотеки генерации кода спасут вас от исходного кода.
  • Аннотации делают ваш класс красивым.

Минусы:

  • Это хорошо работает для простых классов. Сделать сложный класс пригодным для продажи может быть сложно.
  • Ломбок и АспектЖ не очень хорошо играют вместе. [подробности]
  • Смотрите мои предупреждения.

Хрисей

Предупреждение!

Hrisey имеет известную проблему с Java 8 и поэтому в настоящее время не может использоваться для разработки под Android. Смотрите # 1 Не удается найти символьные ошибки (JDK 8) .

Хризей основан на Ломбоке . Класс Parcelable с использованием 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

Класс Parcelable с использованием 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);

Parceler в 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 в файле сборки 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 Parcelable для Kotlin и Java. PaperParcel поддерживает классы данных Kotlin, Google AutoValue через расширение 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;
    }

}

В Android-склонный плагин помогает в работе с процессорами аннотаций в сочетании с Android Studio.


7

Я нашел самый простой способ создать класс Parcelable

введите описание изображения здесь


1
это хорошо работает для небольших данных, но если мы возьмем сложные данные, это не сработает
Manohar Reddy

1

Это очень просто, вы можете использовать плагин на Android Studio, чтобы сделать объекты 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 для преобразования любого вашего пользовательского класса в 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; }
}

Вы можете создать объект класса Example и обернуть его через Parcels и отправить как связку через намерение. например

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

Теперь, чтобы получить объект Custom Class, просто используйте

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

0

Android Parcable имеет несколько уникальных вещей. Те приведены ниже:

  1. Вы должны прочитать Посылку как тот же порядок, в котором вы помещаете данные в посылку.
  2. Посылка будет пустой после прочтения из посылки. Это если у вас есть 3 данные на вашей посылке. Тогда после прочтения 3 раза посылка будет пустой.

Пример: чтобы сделать класс Parceble, необходимо реализовать Parceble. У Percable есть 2 метода:

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

Предположим, у вас есть класс Person, и у него есть 3 поля: firstName, lastName и age. После реализации интерфейса 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код дан ниже:

Положите в Extra :

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

Получите Extra:

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 в вашем классе, а затем поместите курсор на «Implements 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
Хотя этот фрагмент кода может решить вопрос, в том числе объяснение действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причин, по которым вы предлагаете код. Также постарайтесь не переполнять ваш код пояснительными комментариями, это снижает удобочитаемость кода и пояснений!
Ашиш Ахаджа
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.