Jak mogę nadać obiektom niestandardowym możliwość paczkowania?


338

Staram się, aby moje przedmioty można było nadawać na działce. Mam jednak obiekty niestandardowe, które mają ArrayListatrybuty innych obiektów niestandardowych, które utworzyłem.

Jaki byłby najlepszy sposób to zrobić?

Odpowiedzi:


431

Przykłady tego można znaleźć tutaj , tutaj (kod jest pobierany tutaj) i tutaj .

Możesz do tego utworzyć klasę POJO, ale musisz dodać dodatkowy kod, aby to zrobić Parcelable. Zobacz implementację.

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

Po utworzeniu tej klasy możesz łatwo przepuścić obiekty tej klasy przez Intentpodobne i odzyskać ten obiekt w działaniu docelowym.

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

Tutaj uczeń jest kluczem, którego potrzebujesz, aby rozpakować dane z pakietu.

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

Ten przykład pokazuje tylko Stringtypy. Możesz jednak spakować dowolne dane. Wypróbuj to.

EDYCJA: Kolejny przykład , sugerowany przez Rukmal Dias .


@Rukmal Dias 10x. W rzeczywistości muszę edytować swoją odpowiedź i dodać trochę kodu, ponieważ linki te przestaną być aktywne w przyszłości.
fikcja

16
OP pyta, jak przekazać niestandardowe obiekty, a nie zwykły ciąg. Każdy może przekazać zwykłe ciągi znaków. Czy możesz wyjaśnić, w jaki sposób utworzyć go za pomocą OBIEKTU NIESTANDARDOWEGO

Czy muszę zaimplementować części do kodowania / dekodowania, jeśli wysyłam je tylko za pomocą LocalBroadcastManager? Czy wystarczy wdrożyć Paczkę i umieścić jako dodatkową?
JohnyTex,

Dlaczego używasz tablicy ciągów zamiast po prostu pisać kolejno?
Quentin Roy

Czy kolejność elementów podczas tworzenia tablicy łańcuchów wewnątrz writeToParcelmetody ma znaczenie?
Prakhar Mohan Srivastava



56

1. Importuj Android Parcelable code generator

wprowadź opis zdjęcia tutaj

2. Utwórz klasę

public class Sample {
    int id;
    String name;
}

3. Wygeneruj> Paczkowany z menu

wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj

Gotowy.


7
Dla tych, którzy nie wiedzą, gdzie znajduje się okno dialogowe Przeglądaj repozytoria: File > Settings... > Pluginsi kliknij Browse repositories...przycisk.
DaedalusAlpha

Dziękuję, bardzo pomogłem!
Strahinja Ajvaz

21

W jaki sposób? Z adnotacjami.

Po prostu adnotujesz POJO specjalną adnotacją, a biblioteka zajmie się resztą.

Ostrzeżenie!

Nie jestem pewien, czy Hrisey, Lombok i inne biblioteki do generowania kodu są kompatybilne z nowym systemem kompilacji Androida. Mogą lub nie mogą ładnie grać z kodem wymiany na gorąco (np. JRebel, Instant Run).

Plusy:

  • Biblioteki generowania kodu oszczędzają Cię od kodu źródłowego.
  • Adnotacje sprawiają, że Twoja klasa jest piękna.

Cons:

  • Działa dobrze dla prostych klas. Ułożenie paczki złożonej klasy może być trudne.
  • Lombok i AspectJ nie grają dobrze razem. [Detale]
  • Zobacz moje ostrzeżenia.

Hrisey

Ostrzeżenie!

Hrisey ma znany problem z Javą 8 i dlatego nie można go obecnie używać do programowania Androida. Zobacz nr 1 Nie można znaleźć błędów symboli (JDK 8) .

Hrisey opiera się na Lombok . Klasa działki przy użyciu Hrisey :

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

Teraz nie musisz wdrażać żadnych metod interfejsu Parcelable. Hrisey wygeneruje cały wymagany kod podczas fazy wstępnego przetwarzania.

Hrisey w zależnościach Gradle:

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

Zobacz tutaj obsługiwane typy. ArrayListJest wśród nich.

Zainstaluj wtyczkę - Hrisey xor Lombok * - dla swojego IDE i zacznij korzystać z jej niesamowitych funkcji!

wprowadź opis zdjęcia tutaj
* Nie włączaj wtyczek Hrisey i Lombok razem, bo pojawi się błąd podczas uruchamiania IDE.


Paczka

Klasa paczki za pomocą Parceler :

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

Aby użyć wygenerowanego kodu, możesz odwoływać się do wygenerowanej klasy bezpośrednio lub za pomocą Parcelsklasy narzędzi, używając

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

Aby wyłuskać @Parcel, po prostu wywołaj następującą metodę Parcelsklasy

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

Działka w zależnościach Gradle:

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

Poszukaj w README obsługiwanych typów atrybutów .


AutoParcel

AutoParcel to AutoValue rozszerzenie które umożliwia generowanie wartości Parcelable.

Po prostu dodaj implements Parcelabledo swoich @AutoValuemodeli z adnotacjami:

@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 w pliku kompilacji 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 to procesor adnotacji, który automatycznie generuje bezpieczny kod paczkowany dla Kotlin i Java. PaperParcel obsługuje Klasy danych Kotlin, AutoValue Google'a poprzez rozszerzenie AutoValue lub zwykłe obiekty Java Bean.

Przykład użycia z dokumentów .
Dodaj adnotację do swojej klasy danych @PaperParcel, zaimplementuj PaperParcelablei dodaj instancję statyczną JVM, PaperParcelable.Creatornp .:

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

Dla użytkowników Kotlin, patrz Wykorzystanie Kotlin ; Dla użytkowników AutoValue, zobacz Korzystanie z AutoValue .


ParcelableGenerator

ParcelableGenerator (README jest napisane po chińsku i nie rozumiem tego. Mile widziane są wkłady w tę odpowiedź od twórców anglojęzycznych)

Przykład użycia z 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;
    }

}

W android-apt asysty plugin w pracy z procesorami adnotacji w połączeniu z systemem Android Studio.


7

Znalazłem najprostszy sposób na stworzenie klasy Parcelable

wprowadź opis zdjęcia tutaj


1
działa dobrze dla małych danych, ale jeśli weźmiemy złożone dane, to nie zadziała
Manohar Reddy,

1

To bardzo proste, możesz użyć wtyczki na Android Studio, aby tworzyć obiekty Paczkowate.

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
Co masz na myśli?
naXa

0

Teraz możesz użyć biblioteki Parceler do konwersji dowolnej niestandardowej klasy na paczkową. Dodaj adnotację do swojej klasy POJO za pomocą @Parcel . na przykład

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

możesz utworzyć obiekt klasy Przykład i owinąć Paczki i wysłać jako pakiet przez zamiar. na przykład

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

Teraz, aby uzyskać obiekt klasy niestandardowej, wystarczy użyć

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

0

Paczka z Androidem ma kilka unikalnych cech. Poniżej podano:

  1. Musisz przeczytać Paczkę jako to samo zamówienie, w którym umieszczasz dane na paczce.
  2. Paczka opróżni się po odczytaniu z paczki. To znaczy, jeśli masz 3 dane na swojej paczce. Następnie po przeczytaniu 3 razy paczka będzie pusta.

Przykład: aby stworzyć klasę Parceble, należy zaimplementować Parceble. Percable ma 2 metody:

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

Załóżmy, że masz klasę Person, która ma 3 pola: FirstName, LastName i wiek. Po wdrożeniu interfejsu Parceble. ten interfejs podano poniżej:

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

}

W tej writeToParcelmetodzie piszemy / dodajemy dane na Paczce w zamówieniu. Następnie musimy dodać poniższy kod do odczytu danych z paczki:

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

Tutaj klasa Person bierze paczkę i pobiera dane w tej samej kolejności podczas pisania.

Teraz podczas intencji getExtraiputExtra kodu podano poniżej:

Dodaj dodatkowe :

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

Uzyskaj dodatkowe:

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

Klasa Full Person znajduje się poniżej :

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

Utwórz klasę działki bez wtyczki w Android Studio

implementuje Parcelable w twojej klasie, a następnie umieść kursor na „implements Parcelable” i naciśnij Alt+Enteri wybierz Add Parcelable implementation(patrz zdjęcie). Otóż ​​to.

wprowadź opis zdjęcia tutaj


-3

Położyć: bundle.putSerializable("key",(Serializable) object);

Aby uzyskać: List<Object> obj = (List<Object>)((Serializable)bundle.getSerializable("key"));


3
Doprowadzi to do tego, ClassCastExceptionjeśli obiekt nie zaimplementuje Serializable.
naXa

1
Ten fragment kodu może rozwiązać pytanie, ale wyjaśnienie naprawdę pomaga poprawić jakość posta. Pamiętaj, że w przyszłości odpowiadasz na pytanie dla czytelników, a ci ludzie mogą nie znać przyczyn Twojej sugestii kodu. Staraj się również nie tłoczyć kodu objaśniającymi komentarzami, co zmniejsza czytelność zarówno kodu, jak i objaśnień!
Ashish Ahuja
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.