Как я могу сделать свои собственные объекты 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.