هل لديك سؤال؟ اسأله على StackOverflow.
هل وجدت مشكلة؟ يرجى الإبلاغ عن ذلك.
في Android، تعد Parcelables طريقة رائعة لإجراء تسلسل لكائنات Java بين السياقات. بالمقارنة مع التسلسل التقليدي، تستغرق الطرود وقتًا أقل بمقدار 10 مرات لإجراء التسلسل وإلغاء التسلسل. ومع ذلك، هناك عيب كبير في Parcelables. تحتوي الطرود على الكثير من التعليمات البرمجية النموذجية. لتنفيذ Parcelable، يجب أن تعكس أساليب writeToParcel()
و createFromParcel()
بحيث تقرأ وتكتب إلى الطرود بنفس الترتيب. أيضًا، يجب أن يحدد Parcelable public static final Parcelable.Creator CREATOR
حتى تتمكن البنية التحتية لنظام Android من الاستفادة من رمز التسلسل.
Parceler هي مكتبة لإنشاء الأكواد البرمجية تقوم بإنشاء كود مصدر Android Parcelable المعياري. لم يعد يتعين عليك تنفيذ واجهة Parcelable أو writeToParcel()
أو createFromParcel()
أو public static final CREATOR
. ما عليك سوى إضافة تعليق توضيحي إلى POJO باستخدام @Parcel
وسيقوم Parceler بالباقي. نظرًا لأن Parceler يستخدم معالج التعليقات التوضيحية Java JSR-269، ليست هناك حاجة لتشغيل أداة يدويًا لإنشاء رمز Parcelable. ما عليك سوى إضافة تعليق توضيحي إلى Java Bean الخاص بك، وتجميعه، وبذلك تكون قد انتهيت. افتراضيًا، سيقوم Parceler بإجراء تسلسل لحقول المثيل الخاص بك مباشرةً:
@ 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 ; }
}
احرص على عدم استخدام الحقول الخاصة عند استخدام استراتيجية تسلسل الحقول الافتراضية لأنها ستؤدي إلى فرض عقوبة على الأداء بسبب الانعكاس.
لاستخدام الكود الذي تم إنشاؤه، يمكنك الرجوع إلى الفئة التي تم إنشاؤها مباشرة، أو عبر فئة الأداة المساعدة Parcels
:
Parcelable wrapped = Parcels . wrap ( new Example ( "Andy" , 42 ));
لإلغاء الإشارة إلى @Parcel
، ما عليك سوى استدعاء الأسلوب Parcels.unwrap()
:
Example example = Parcels . unwrap ( wrapped );
example . getName (); // Andy
example . getAge (); // 42
بالطبع، يمكن إضافة Parcelable
المغلف إلى Android Bundle للنقل من نشاط إلى آخر:
Bundle bundle = new Bundle ();
bundle . putParcelable ( "example" , Parcels . wrap ( example ));
وتم إلغاء الإشارة إليه في طريقة onCreate()
:
Example example = Parcels . unwrap ( getIntent (). getParcelableExtra ( "example" ));
تعمل تقنية الالتفاف وإلغاء التغليف هذه بشكل جيد مع نمط Intent Factory. بالإضافة إلى ذلك، يتم دعم Parceler بواسطة المكتبات التالية:
Transfuse - يسمح باستخدام الفاصوليا المشروحة @Parcel
مع الحقنة @Extra
.
FragmentArgs - يستخدم محول ParcelerArgsBundler
لالتفاف وإلغاء تغليف الفاصوليا المشروحة @Parcel
بمعلمات الجزء.
Dart - يكتشف تلقائيًا الحبوب المشروحة @Parcel
ويزيل تغليفها تلقائيًا عند استخدام @InjectExtra
.
AndroidAnnotations - يكتشف تلقائيًا الفاصوليا ذات التعليقات التوضيحية @Parcel
ويقوم بتغليفها/إلغاء تغليفها تلقائيًا عند استخدام @Extra
و @FragmentArg
و @InstanceState
والتعليقات التوضيحية الأخرى ذات الصلة Bundle
.
ActivityStarter - يدعم كائنات Parceler أصلاً كوسائط للأنشطة والأجزاء والخدمات وما إلى ذلك.
Remoter - يدعم كائنات Parceler أصلاً كوسائط في واجهاتRemoter.
يمكن استخدام عدد محدد فقط من الأنواع كسمات لفئة @Parcel
. تتضمن القائمة التالية الأنواع المعينة:
byte
double
float
int
long
char
boolean
String
IBinder
Bundle
SparseArray
لأي من الأنواع المعينة*
SparseBooleanArray
ObservableField
List
و ArrayList
و LinkedList
لأي من الأنواع المعينة*
Map
و HashMap
و LinkedHashMap
و SortedMap
و TreeMap
لأي من الأنواع المعينة*
Set
و HashSet
و SortedSet
و TreeSet
و LinkedHashSet
من أي من الأنواع المعينة*
Parcelable
Serializable
صفيف من أي من الأنواع المعينة
أي فئة أخرى تم تعليقها باستخدام @Parcel
*سيحدث خطأ في الطرد إذا لم يتم تعيين المعلمة العامة.
يدعم Parceler أيضًا أيًا من الأنواع المذكورة أعلاه مباشرةً. يعد هذا مفيدًا بشكل خاص عند التعامل مع مجموعات من الفئات الموضحة بـ @Parcel
:
Parcelable listParcelable = Parcels . wrap ( new ArrayList < Example >());
Parcelable mapParcelable = Parcels . wrap ( new HashMap < String , Example >());
لاحظ أن Parceler لا يقوم بإلغاء تغليف التسلسلات الهرمية للوراثة، لذلك سيتم إلغاء تغليف أي حقول متعددة الأشكال كمثيلات للفئة الأساسية. وذلك لأن Parceler يختار الأداء بدلاً من التحقق من .getClass()
لكل جزء من البيانات.
@ 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
راجع قسم التسلسل المخصص للحصول على مثال للعمل مع الحقول متعددة الأشكال.
يقدم Parceler عدة خيارات لكيفية إجراء تسلسل وإلغاء تسلسل كائن بالإضافة إلى التسلسل الميداني الموضح أعلاه.
قد يتم تكوين Parceler لإجراء تسلسل باستخدام أساليب getter وsetter ومنشئ غير فارغ. بالإضافة إلى ذلك، قد يتم ربط الحقول والأساليب ومعلمات المُنشئ باستخدام التعليق التوضيحي @ParcelProperty
. وهذا يدعم عددًا من استراتيجيات الفاصوليا بما في ذلك الثبات والفاصوليا التقليدية.
لتكوين تسلسل الطريقة الافتراضية، ما عليك سوى تكوين التعليق التوضيحي @Parcel
باستخدام 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 ; }
}
لاستخدام مُنشئ مع التسلسل، قم بتعليق المُنشئ المطلوب باستخدام التعليق التوضيحي @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 ; }
}
في حالة وجود مُنشئ فارغ، سيستخدم Parceler هذا المُنشئ ما لم يتم إضافة مُنشئ آخر.
يمكنك أيضًا مزج تقنيات التسلسل ومطابقتها باستخدام التعليق التوضيحي @ParcelProperty
. في المثال التالي، تتم كتابة firstName
واسم lastName
على الحبة باستخدام المُنشئ بينما تتم قراءة firstName
من الحبة باستخدام الحقل ويتم قراءة lastName
باستخدام طريقة getLastName()
. يتم تنسيق معلمات firstName
واسم lastName
بواسطة أسماء المعلمات "first"
و "last"
بشكل محترم.
@ 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 ; }
}
بالنسبة للسمات التي لا ينبغي إجراء تسلسل لها باستخدام Parceler، قد يتم وضع تعليقات توضيحية على حقل السمة أو getter أو setter بواسطة @Transient
.
يدعم Parceler العديد من الأنماط المختلفة التي تتمحور حول POJO. يسمح هذا باستخدام فئات @Parcel
المشروحة مع المكتبات الأخرى المستندة إلى POJO، بما في ذلك ما يلي:
جيسون
عالم
خزانة
XML بسيط
DBFlow
كبديل لاستخدام المُنشئ مباشرةً، يدعم Parceler استخدام Static Factory المشروح لإنشاء مثيل للفئة المحددة. يدعم هذا النمط معالج التعليقات التوضيحية AutoValue من Google/مكتبة إنشاء التعليمات البرمجية لإنشاء وحدات غير قابلة للتغيير. واجهات Parceler مع AutoValue عبر التعليق التوضيحي @ParcelFactory
، الذي يعين طريقة مصنع ثابتة في تسلسل @Parcel
المشروح:
@ 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 بإنشاء فئة مختلفة عن @Parcel
المشروحة، لذلك، تحتاج إلى تحديد الفئة التي يجب أن ينشئها Parceler في فئة الأداة المساعدة Parcels
:
Parcelable wrappedAutoValue = Parcels . wrap ( AutoValueParcel . class , AutoValueParcel . create ( "example" ));
ولإلغاء التسلسل:
AutoValueParcel autoValueParcel = Parcels . unwrap ( wrappedAutoValue );
يتضمن @Parcel
معلمة اختيارية لتضمين مُسلسل يدوي ParcelConverter
للحالة التي يكون فيها التسلسل الخاص ضروريًا. يوفر هذا خيارًا أنظف لاستخدام فئات Parcelable بدلاً من تنفيذها يدويًا.
يوضح التعليمة البرمجية التالية استخدام ParcelConverter
لإلغاء التسلسل الهرمي للميراث أثناء إلغاء التسلسل.
@ 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 مع سلسلة من الفئات الأساسية لتسهيل تحويل المجموعة الموجودة ضمن حزمة org.parceler.converter
الخاصة بواجهة برمجة التطبيقات. تعتني هذه الفئات الأساسية بمجموعة متنوعة من المهام الصعبة أو المطولة التي تتعامل مع المجموعات بما في ذلك عمليات التحقق من القيمة الفارغة وتكرار التجميع. على سبيل المثال، يمكن كتابة ParcelConverter
أعلاه باستخدام 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 ()));
}
}
بالنسبة للفئات التي لا يتوفر مصدر Java المقابل لها، يمكن للمرء تضمين الفئة كقطعة باستخدام التعليق التوضيحي @ParcelClass
. قد يتم الإعلان عن هذا التعليق التوضيحي في أي مكان مناسب في المصدر المترجم. على سبيل المثال، يمكن للمرء تضمين @ParcelClass
مع تطبيق Android:
@ ParcelClass ( LibraryParcel . class )
public class AndroidApplication extends Application {
//...
}
يمكن الإعلان عن تعليقات توضيحية @ParcelClass
متعددة باستخدام التعليق التوضيحي @ParcelClasses
.
بالإضافة إلى ذلك، يمكن تكوين الفئات المشار إليها بواسطة @ParcelClass
باستخدام التعليق التوضيحي @Parcel
. يسمح هذا بتكوين التسلسل من خلال أي معلمة متاحة في التعليق التوضيحي @Parcel
بما في ذلك تقنية التسلسل أو الفئات المراد تحليلها.
إحدى التقنيات المفيدة هي القدرة على تحديد المحولات المخصصة العامة لنوع ما:
@ ParcelClass (
value = LibraryParcel . class ,
annotation = @ Parcel ( converter = LibraryParcelConverter . class ))
class SomeClass {}
وهذا يسمح بالتحكم الدقيق في فئة غير متاحة للتعديل المباشر.
من الممارسات الشائعة لبعض المكتبات أن تطلب حبة لتوسيع فئة أساسية. على الرغم من أنها ليست الحالة الأمثل، إلا أن Parceler يدعم هذه الممارسة من خلال السماح بتكوين الفئات الموجودة في التسلسل الهرمي للميراث لتحليلها عبر معلمة التحليل:
@ Parcel ( analyze = { One . class , Three . class })
class One extends Two {}
class Two extends Three {}
class Three extends BaseClass {}
في هذا المثال، سيتم إجراء تسلسل فقط لحقول الفئتين One
و Three
، مع تجنب معلمات الفئتين BaseClass
و Two
.
تبحث فئة الأداة المساعدة Parcels عن الفئة المحددة للالتفاف حسب الفئة. لأسباب تتعلق بالأداء، يتجاهل هذا الوراثة، سواء الفئات الفائقة أو الأساسية. هناك حلان لهذه المشكلة. أولاً، يمكن تحديد أنواع إضافية لربطها بالنوع المحدد عبر معاملات 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
ثانيًا، يمكن أيضًا تحديد نوع الفئة عند استخدام التابع Parcels.wrap()
:
ExampleProxy proxy = new ExampleProxy ();
Parcels . wrap ( Example . class , proxy );
لتكوين Proguard، قم بإضافة الأسطر التالية إلى ملف تكوين Proguard الخاص بك. سيحتفظ هذا بالملفات المتعلقة بفئة الأداة المساعدة Parcels
ومثيل Parcelable
CREATOR
: er
#مكتبة الطرود -الحفاظ على واجهة org.parceler.Parcel -keep @org.parceler.Parcel class * { *; } - احتفظ بالفصل **$$Parcelable { *; }
يمكنك تنزيل Parceler باعتباره تابعًا لـ 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 >
أو جرادل:
implementation ' org.parceler:parceler-api:1.1.12 '
annotationProcessor ' org.parceler:parceler:1.1.12 '
أو من مافن سنترال.
حقوق الطبع والنشر 2011-2015 جون إريكسن مرخص بموجب ترخيص Apache، الإصدار 2.0 ("الترخيص")؛ لا يجوز لك استخدام هذا الملف إلا وفقًا للترخيص. يمكنك الحصول على نسخة من الترخيص على http://www.apache.org/licenses/LICENSE-2.0 ما لم يكن ذلك مطلوبًا بموجب القانون المعمول به أو تم الاتفاق عليه كتابيًا، البرمجيات الموزعة بموجب الترخيص يتم توزيعها على أساس "كما هي"، دون ضمانات أو شروط من أي نوع، سواء كانت صريحة أو ضمنية. راجع الترخيص لمعرفة الأذونات التي تحكم اللغة المحددة و القيود بموجب الترخيص.