Punya pertanyaan? Tanyakan di StackOverflow.
Menemukan masalah? Silakan laporkan.
Di Android, Parcelables adalah cara terbaik untuk membuat serialisasi Objek Java antar Konteks. Dibandingkan dengan Serialisasi tradisional, Parcelables membutuhkan waktu 10x lebih sedikit untuk membuat serialisasi dan deserialisasi. Namun, ada kelemahan besar pada Parcelables. Parcelable berisi banyak sekali kode boilerplate. Untuk mengimplementasikan Parcelable, Anda harus mencerminkan metode writeToParcel()
dan createFromParcel()
sedemikian rupa sehingga keduanya membaca dan menulis ke Parcel dalam urutan yang sama. Selain itu, Parcelable harus mendefinisikan public static final Parcelable.Creator CREATOR
agar infrastruktur Android dapat memanfaatkan kode serialisasi.
Parceler adalah pustaka pembuatan kode yang menghasilkan kode sumber boilerplate Android Parcelable. Anda tidak lagi harus mengimplementasikan antarmuka Parcelable, writeToParcel()
atau createFromParcel()
atau public static final CREATOR
. Anda cukup membubuhi keterangan POJO dengan @Parcel
dan Parceler akan melakukan sisanya. Karena Parceler menggunakan Prosesor Anotasi Java JSR-269, tidak perlu menjalankan alat secara manual untuk menghasilkan kode Parcelable. Cukup beri anotasi pada Java Bean Anda, kompilasi dan Anda selesai. Secara default, Parceler akan membuat serialisasi kolom instance Anda secara langsung:
@ Parcel
public class Example {
String name ;
int age ;
public Example () {}
public Example ( int age , String name ) {
this . age = age ;
this . name = name ;
}
public String getName () { return name ; }
public int getAge () { return age ; }
}
Berhati-hatilah untuk tidak menggunakan kolom pribadi saat menggunakan strategi serialisasi kolom default karena akan menimbulkan penalti kinerja karena refleksi.
Untuk menggunakan kode yang dihasilkan, Anda dapat mereferensikan kelas yang dihasilkan secara langsung, atau melalui kelas utilitas Parcels
:
Parcelable wrapped = Parcels . wrap ( new Example ( "Andy" , 42 ));
Untuk melakukan dereferensi @Parcel
, panggil saja metode Parcels.unwrap()
:
Example example = Parcels . unwrap ( wrapped );
example . getName (); // Andy
example . getAge (); // 42
Tentu saja, Parcelable
yang dibungkus dapat ditambahkan ke Android Bundle untuk ditransfer dari Aktivitas ke Aktivitas:
Bundle bundle = new Bundle ();
bundle . putParcelable ( "example" , Parcels . wrap ( example ));
Dan direferensikan dalam metode onCreate()
:
Example example = Parcels . unwrap ( getIntent (). getParcelableExtra ( "example" ));
Teknik membungkus dan membuka bungkus ini cocok dengan pola Intent Factory. Selain itu, Parceler didukung oleh perpustakaan berikut:
Transfuse - Mengizinkan kacang beranotasi @Parcel
digunakan dengan injeksi @Extra
.
FragmentArgs - Menggunakan adaptor ParcelerArgsBundler
untuk membungkus dan membuka bungkus kacang beranotasi @Parcel
dengan parameter fragmen.
Dart - Deteksi otomatis kacang beranotasi @Parcel
dan secara otomatis membuka bungkusnya saat menggunakan @InjectExtra
.
AndroidAnnotations - Deteksi otomatis kacang beranotasi @Parcel
dan secara otomatis membungkus/membukanya saat menggunakan @Extra
, @FragmentArg
, @InstanceState
dan anotasi terkait Bundle
lainnya.
ActivityStarter - Mendukung objek Parceler asli sebagai argumen untuk Aktivitas, Fragmen, Layanan, dll.
Remoter - Mendukung objek Parceler asli sebagai argumen di antarmuka @Remoter.
Hanya sejumlah tipe tertentu yang dapat digunakan sebagai atribut kelas @Parcel
. Daftar berikut mencakup tipe yang dipetakan:
byte
double
float
int
long
char
boolean
String
IBinder
Bundle
SparseArray
dari semua jenis yang dipetakan*
SparseBooleanArray
ObservableField
List
, ArrayList
dan LinkedList
dari jenis apa pun yang dipetakan*
Map
, HashMap
, LinkedHashMap
, SortedMap
, dan TreeMap
dari jenis apa pun yang dipetakan*
Set
, HashSet
, SortedSet
, TreeSet
, LinkedHashSet
dari jenis apa pun yang dipetakan*
Parcelable
Serializable
Array dari salah satu tipe yang dipetakan
Kelas lain mana pun yang dianotasi dengan @Parcel
*Parcel akan error jika parameter generik tidak dipetakan.
Parceler juga mendukung semua jenis di atas secara langsung. Hal ini sangat berguna ketika berhadapan dengan koleksi kelas yang dianotasi dengan @Parcel
:
Parcelable listParcelable = Parcels . wrap ( new ArrayList < Example >());
Parcelable mapParcelable = Parcels . wrap ( new HashMap < String , Example >());
Perhatikan bahwa Parceler tidak membuka bungkusan hierarki warisan, sehingga bidang polimorfik apa pun akan dibuka bungkusnya sebagai instance kelas dasar. Hal ini karena Parceler memilih performa dibandingkan memeriksa .getClass()
untuk setiap bagian data.
@ Parcel
public class Example {
public Parent p ;
@ ParcelConstructor Example ( Parent p ) { this . p = p ; }
}
@ Parcel public class Parent {}
@ Parcel public class Child extends Parent {}
Example example = new Example ( new Child ());
System . out . println ( "%b" , example . p instanceof Child ); // true
example = Parcels . unwrap ( Parcels . wrap ( example ));
System . out . println ( "%b" , example . p instanceof Child ); // false
Lihat bagian Serialisasi Kustom untuk contoh bekerja dengan bidang polimorfik.
Parceler menawarkan beberapa pilihan cara membuat serialisasi dan deserialisasi suatu objek selain serialisasi berbasis bidang yang terlihat di atas.
Parceler dapat dikonfigurasi untuk membuat serialisasi menggunakan metode pengambil dan penyetel serta konstruktor yang tidak kosong. Selain itu, bidang, metode, dan parameter konstruktor dapat dikaitkan menggunakan anotasi @ParcelProperty
. Hal ini mendukung sejumlah strategi kacang termasuk kekekalan dan kacang pengambil/penyetel tradisional.
Untuk mengonfigurasi serialisasi metode default, cukup konfigurasikan anotasi @Parcel
dengan Serialization.BEAN
:
@ Parcel ( Serialization . BEAN )
public class Example {
private String name ;
private int age ;
private boolean enabled ;
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 ; }
public boolean isEnabled () { return enabled ; }
public void setEnabled ( boolean enabled ) { this . enabled = enabled ; }
}
Untuk menggunakan konstruktor dengan serialisasi, beri anotasi pada konstruktor yang diinginkan dengan anotasi @ParcelConstructor
:
@ Parcel ( Serialization . BEAN )
public class Example {
private final String name ;
private final int age ;
private boolean enabled ;
@ ParcelConstructor
public Example ( int age , String name , boolean enabled ) {
this . age = age ;
this . name = name ;
this . enabled = enabled ;
}
public String getName () { return name ; }
public int getAge () { return age ; }
public boolean isEnabled () { return enabled ; }
}
Jika ada konstruktor kosong, Parceler akan menggunakan konstruktor tersebut kecuali konstruktor lain diberi anotasi.
Anda juga dapat memadupadankan teknik serialisasi menggunakan anotasi @ParcelProperty
. Dalam contoh berikut, firstName
dan lastName
ditulis ke bean menggunakan konstruktor sementara firstName
dibaca dari bean menggunakan field dan lastName
dibaca menggunakan metode getLastName()
. Parameter firstName
dan lastName
dikoordinasikan dengan nama parameter "first"
dan "last"
secara berurutan.
@ Parcel
public class Example {
@ ParcelProperty ( "first" )
String firstName ;
String lastName ;
@ ParcelConstructor
public Example ( @ ParcelProperty ( "first" ) String firstName , @ ParcelProperty ( "last" ) String lastName ){
this . firstName = firstName ;
this . lastName = lastName ;
}
public String getFirstName () { return firstName ; }
@ ParcelProperty ( "last" )
public String getLastName () { return lastName ; }
}
Untuk atribut yang tidak boleh diserialkan dengan Parceler, bidang atribut, pengambil, atau penyetel dapat dianotasi dengan @Transient
.
Parceler mendukung banyak gaya berbeda yang berpusat di sekitar POJO. Hal ini memungkinkan kelas beranotasi @Parcel
untuk digunakan dengan perpustakaan berbasis POJO lainnya, termasuk yang berikut:
GSON
Dunia
Lemari
XML sederhana
Aliran DB
Sebagai alternatif untuk menggunakan konstruktor secara langsung, Parceler mendukung penggunaan Static Factory yang diberi anotasi untuk membangun sebuah instance dari kelas tertentu. Gaya ini mendukung pemroses anotasi AutoValue/pustaka pembuatan kode Google untuk menghasilkan kacang yang tidak dapat diubah. Parceler berinteraksi dengan AutoValue melalui anotasi @ParcelFactory
, yang memetakan metode pabrik statis ke dalam serialisasi @Parcel
yang dianotasi:
@ AutoValue
@ Parcel
public abstract class AutoValueParcel {
@ ParcelProperty ( "value" ) public abstract String value ();
@ ParcelFactory
public static AutoValueParcel create ( String value ) {
return new AutoValue_AutoValueParcel ( value );
}
}
AutoValue menghasilkan kelas yang berbeda dari @Parcel
yang dianotasi, oleh karena itu, Anda perlu menentukan kelas Parceler mana yang harus dibangun di kelas utilitas Parcels
:
Parcelable wrappedAutoValue = Parcels . wrap ( AutoValueParcel . class , AutoValueParcel . create ( "example" ));
Dan untuk melakukan deserialisasi:
AutoValueParcel autoValueParcel = Parcels . unwrap ( wrappedAutoValue );
@Parcel
menyertakan parameter opsional untuk menyertakan serializer manual ParcelConverter
jika serialisasi khusus diperlukan. Ini memberikan opsi yang lebih bersih untuk menggunakan kelas Parcelable dibandingkan menerapkannya secara manual.
Kode berikut menunjukkan penggunaan ParcelConverter
untuk membuka hierarki warisan selama deserialisasi.
@ Parcel
public class Item {
@ ParcelPropertyConverter ( ItemListParcelConverter . class )
public List < Item > itemList ;
}
@ Parcel public class SubItem1 extends Item {}
@ Parcel public class SubItem2 extends Item {}
public class ItemListParcelConverter implements ParcelConverter < List < Item >> {
@ Override
public void toParcel ( List < Item > input , Parcel parcel ) {
if ( input == null ) {
parcel . writeInt (- 1 );
}
else {
parcel . writeInt ( input . size ());
for ( Item item : input ) {
parcel . writeParcelable ( Parcels . wrap ( item ), 0 );
}
}
}
@ Override
public List < Item > fromParcel ( Parcel parcel ) {
int size = parcel . readInt ();
if ( size < 0 ) return null ;
List < Item > items = new ArrayList < Item >();
for ( int i = 0 ; i < size ; ++ i ) {
items . add (( Item ) Parcels . unwrap ( parcel . readParcelable ( Item . class . getClassLoader ())));
}
return items ;
}
}
Parceler juga dikemas dengan serangkaian kelas dasar untuk membuat konversi Koleksi lebih mudah terletak di bawah paket api org.parceler.converter
. Kelas dasar ini menangani berbagai pekerjaan sulit atau bertele-tele yang berhubungan dengan Koleksi termasuk pemeriksaan nol dan iterasi koleksi. Misalnya, ParcelConverter
di atas dapat ditulis menggunakan `ArrayListParcelConverter':
public class ItemListParcelConverter extends ArrayListParcelConverter < Item > {
@ Override
public void itemToParcel ( Item item , Parcel parcel ) {
parcel . writeParcelable ( Parcels . wrap ( item ), 0 );
}
@ Override
public Item itemFromParcel ( Parcel parcel ) {
return Parcels . unwrap ( parcel . readParcelable ( Item . class . getClassLoader ()));
}
}
Untuk kelas yang sumber Java terkaitnya tidak tersedia, seseorang dapat menyertakan kelas tersebut sebagai Parcel dengan menggunakan anotasi @ParcelClass
. Anotasi ini dapat dideklarasikan di mana saja dalam sumber yang dikompilasi sesuai keinginan. Misalnya, seseorang dapat menyertakan @ParcelClass
bersama dengan Aplikasi Android:
@ ParcelClass ( LibraryParcel . class )
public class AndroidApplication extends Application {
//...
}
Beberapa anotasi @ParcelClass
dapat dideklarasikan menggunakan anotasi @ParcelClasses
.
Selain itu, kelas yang direferensikan oleh @ParcelClass
dapat dikonfigurasi menggunakan anotasi @Parcel
. Hal ini memungkinkan konfigurasi serialisasi melalui parameter apa pun yang tersedia di anotasi @Parcel
termasuk teknik serialisasi atau kelas yang akan dianalisis.
Salah satu teknik yang berguna adalah kemampuan untuk menentukan konverter khusus global untuk suatu jenis:
@ ParcelClass (
value = LibraryParcel . class ,
annotation = @ Parcel ( converter = LibraryParcelConverter . class ))
class SomeClass {}
Hal ini memungkinkan kontrol menyeluruh atas kelas yang tidak tersedia untuk modifikasi langsung.
Merupakan praktik umum bagi beberapa perpustakaan untuk memerlukan kacang untuk memperluas kelas dasar. Meskipun ini bukan kasus yang paling optimal, Parceler mendukung praktik ini dengan mengizinkan konfigurasi kelas mana dalam hierarki pewarisan yang akan dianalisis melalui parameter analisis:
@ Parcel ( analyze = { One . class , Three . class })
class One extends Two {}
class Two extends Three {}
class Three extends BaseClass {}
Dalam contoh ini, hanya bidang kelas One
dan Three
yang akan diserialkan, menghindari parameter kelas BaseClass
dan Two
.
Kelas utilitas Parcels mencari kelas tertentu untuk dibungkus berdasarkan kelas. Untuk alasan kinerja, hal ini mengabaikan warisan, baik kelas super maupun kelas dasar. Ada dua solusi untuk masalah ini. Pertama, seseorang dapat menentukan tipe tambahan untuk dikaitkan dengan tipe tertentu melalui parameter implementations
:
class ExampleProxy extends Example {}
@ Parcel ( implementations = { ExampleProxy . class })
class Example {}
ExampleProxy proxy = new ExampleProxy ();
Parcels . wrap ( proxy ); // ExampleProxy will be serialized as a Example
Kedua, seseorang juga dapat menentukan tipe kelas saat menggunakan metode Parcels.wrap()
:
ExampleProxy proxy = new ExampleProxy ();
Parcels . wrap ( Example . class , proxy );
Untuk mengonfigurasi Proguard, tambahkan baris berikut ke file konfigurasi proguard Anda. Ini akan menyimpan file yang terkait dengan kelas utilitas Parcels
dan instance Parcelable
CREATOR
: eh
#Perpustakaan parsel -menjaga antarmuka org.parceler.Parcel -pertahankan kelas @org.parceler.Parcel * { *; } -menjaga kelas **$$Parcelable { *; }
Anda dapat mengunduh Parceler sebagai ketergantungan Maven:
< dependency >
< groupId >org.parceler</ groupId >
< artifactId >parceler</ artifactId >
< version >1.1.12</ version >
< scope >provided</ scope >
</ dependency >
< dependency >
< groupId >org.parceler</ groupId >
< artifactId >parceler-api</ artifactId >
< version >1.1.12</ version >
</ dependency >
atau Gradle:
implementation ' org.parceler:parceler-api:1.1.12 '
annotationProcessor ' org.parceler:parceler:1.1.12 '
Atau dari Maven Central.
Hak Cipta 2011-2015 John Ericksen Berlisensi di bawah Lisensi Apache, Versi 2.0 ("Lisensi"); Anda tidak boleh menggunakan file ini kecuali sesuai dengan Lisensi. Anda dapat memperoleh salinan Lisensi di http://www.apache.org/licenses/LICENSE-2.0 Kecuali diwajibkan oleh hukum yang berlaku atau disetujui secara tertulis, perangkat lunak didistribusikan di bawah Lisensi didistribusikan berdasarkan DASAR "SEBAGAIMANA ADANYA", TANPA JAMINAN ATAU KETENTUAN APAPUN, baik tersurat maupun tersirat. Lihat Lisensi untuk bahasa tertentu yang mengatur izin dan batasan berdasarkan Lisensi.