الـ Parcelable في أندرويد
بسم الله الرحمن الرحيم
لإرسال البيانات بين two activities يوجد عدة طرق, كـ shared Preference و database, لكن الطريقة المباشرة للإرسال هي عن طريق Intent بإستخدام الدوال الخاصة بها putExtra() والتي تتعامل مع جميع الـ Primitive types بطريقة مباشرة, لكن في حال أردنا أن نرسل object أو list of objects سنضطر لإستخدام ما يسمى بـ parcelable.
بداية ما هو الـ parcelable, هو interface يعمل كعمل الـ Serializable في جافا لكن مخصص لأندرويد, يعمل على تحويل الـ object إلى byte واستعادته كـ object مرة أخرى وفي هذه المقالة سنتكلم عنه وعن الية التعامل معه.
لنفرض أن لدينا Student class
public class Student {
private String name;
private int id;
public Student(String name, int id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
ولدينا two Activities الأولى MainActivity والثانية ShowStudentActivity, سنحاول نقل object واحد ومن ثم نقل list of object.
سنقسم هذه المقالة إلى ثلاثة أقسام:
- نقوم بعمل implementation لـ Parcelable
- نقوم بتمرير object
- نقوم بتمرير list of object
لنبدأ بعمل implementation لـ Parcelable
public class Student implements Parcelable {
private String name;
private int id;
public Student(String name, int id) {
this.name = name;
this.id = id;
}
protected Student(Parcel in) {
name = in.readString();
id = in.readInt();
}
public static final Creator<Student> CREATOR = new Creator<Student>() {
@Override
public Student createFromParcel(Parcel in) {
return new Student(in);
}
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public int describeContents() {
return hashCode();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(id);
}
}
بداية قمنا بعمل implementation لـ Parcelable, ثم override لدالتين, الأولى describeContents والتي ترجع hash code الخاص بـ class, والثانية writeToParcel تحول data members إلى Parcel class, فنستخدم دوال Parcel class لتخزين بياناتنا, وهنا ينبغي الانتباه لترتيب data members عند الكتابة والقراءة حيث أنه في حال ما حدث تغيير في الترتيب قد يكون هناك crash لتطبيق.
@Override
public int describeContents() {
return hashCode();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(id);
}
بعد ذلك قمنا ببناء static field يسمى CREATOR وهو يستخدم من النظام لاستعادة البيانات - unparcel - , بداخلة دالتين أخرتين الأولى createFromParcel وهي تستخدم لإعادة بناء الـ object, ونلاحظ بداخلها استدعاء لـ constructor يستقبل parcel object لذلك سنقوم ببناء هذا constructor لاحقا, الدالة الثانية newArray وهي تستدعى في حال كان لديك مصفوفة - array - من الـ Parcelable ثم تستدعي الدالة الأولى createFromParcel عند بناء كل عنصر داخل هذه المصفوفة.
public static final Creator<Student> CREATOR = new Creator<Student>() {
@Override
public Student createFromParcel(Parcel in) {
return new Student(in);
}
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
كما ذكرنا أن دالة createFromParcel تستدعي constructor يستقبل parcel object, ولهذا سنقوم ببنائه, وكما ذكرنا أيضا أن الترتيب مطلوب كما, قمنا بكتابة name أولا ثم id, سنقرأ بنفس الترتيب كالتالي
protected Student(Parcel in) {
name = in.readString();
id = in.readInt();
}
وبهذا يكون لدينا class نستطيع نقول بياناته بين الـ activity بشكل بسيط وسلس
سنقوم الان بنقل object واحد من هذا class إلى Activity أخرى, كما هو معلوم التنقل بين الـ activites يكون دائما بإستخدام Intent, ولنقل البيانات نستخدم الدوال المساعدة في عملية النقل putExtra, هذه الدالة تستيع التعامل مع عدة انواع من المتغيرات - overloaded method - منها ال Parcelable, كما نلاحظ من داخل Intent class
public @NonNull Intent putExtra(String name, Parcelable value) {
if (mExtras == null) {
mExtras = new Bundle();
}
mExtras.putParcelable(name, value);
return this;
}
لذا فيمكنا إرسال object كالتالي
Student student = new Student("Kream",16);
Intent i = new Intent(this,ShowStudentActivity.class);
i.putExtra("Key",student);
startActivity(i);
واستقباله في ShowStudentActivity بهذه الطريقة
public class ShowStudentActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_student);
Student student = getIntent().getParcelableExtra("Key");
}
}
سنقوم الان بنقل ArrayList من نفس الـ class بنفس الطريقة
ArrayList<Student> students = new ArrayList<>();
students.add(new Student("Ali",18));
students.add(new Student("Ahmed",19));
students.add(new Student("Adel",20));
students.add(new Student("Khaled",23));
students.add(new Student("Kream",16));
Intent i = new Intent(this,ShowStudentActivity.class);
i.putParcelableArrayListExtra("students", students);
startActivity(i);
ثم استعادتها في الـ Activity الأخرى
public class ShowStudentActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_student);
ArrayList<Student> students = getIntent().getParcelableArrayListExtra("students");
}
}
أندرويد ستديو له عدد من الإختصارات تسهل عمل implementation لـ Parcelable استعرضتها في هذا الفيديو:
إلى هنا نكون قد وصلنا إلى نهاية هذه المقالة, والسلام عليكم ورحمة الله وبركاته
المصادر:
https://www.survivingwithandroid.com/2012/09/passing-data-between-activities-2.html
https://stackoverflow.com/questions/22037801/parcelable-what-is-newarray-for
https://developer.android.com/reference/android/os/Parcel.html
التعليقات (0)
لايوجد لديك حساب في عالم البرمجة؟
تحب تنضم لعالم البرمجة؟ وتنشئ عالمك الخاص، تنشر المقالات، الدورات، تشارك المبرمجين وتساعد الآخرين، اشترك الآن بخطوات يسيرة !