انتقال داده بین اکتیویتی ها با کمک Android Parcelable

انتقال داده بین اکتیویتی ها با کمک Android Parcelable


به طور معمول اپلیکیشن های اندروید دارای چندین اکتیویتی هستند و لازم است داده ها بین این اکتیویتی ها رد و بدل شوند. برای نمونه یک اکتیویتی اولیه با لیستی از عناصر و اکتیویتی دوم که به نمایش این عناصر می پردازد را در نظر بگیرید. جهت جابجایی از یک اکتیویتی به دیگری از کلاس intent جهت برقراری ارتباط بین آنها استفاده می شود، این کار شما را قادر به لانچ یک اکتیویتی و بازگرداندن اختیاری آن در آینده می سازد.

ارسال داده بین اکتیویتی ها بخشی از فرآیند به شمار می رود و این کار توسط متدهای putExtra و getExtra از آبجکت intent صورت می پذیرد. ایده اصلی تسهیل فرآیند ارسال انواع گوناگون داده به شکل زیر می باشد:

//Inside first activity

Intent intent = new Intent(MainActivity.this, DetailActivity.class);

intent.putExtra("name", "John Smith");

intent.putExtra("age", 26);

//inside second activity

Intent intent = getIntent();

String suburb = intent.getStringExtra("name");

Integer age = intent.getIntExtra("age");

این روش برای انواع داده های مقدماتی مانند رشته، بولین و اعداد صحیح کفایت می کند، اما برای آبجکت ها مناسب نیست، چنانچه مایل به ارسال آبجکت و داده های آن از یک اکتیویتی به دیگری باشید چه باید بکنید؟ برای این منظور می توان رابط parcelable را مورد استفاده قرار داد.

معرفی رابط Parcelable

از آنجا که آبجکت ها ممکن است شامل انواع گوناگونی از داده ها باشند، از این رو نمی توانید جهت جابجایی مقادیر از putExtra استفاده کنید. جاوا دارای قابلیت serialize کردن آبجکت ها می باشد، اما این فرآیند کند است و سیستم نیازمند اجرای جابجایی های سنگینی برای انتقال داده ها می باشد. Parcelable یک رابط اندرویدی است که برای serialize کردن یک کلاس و ویژگی های آن جهت انتقال از یک اکتیویتی به دیگری مورد استفاده قرار می گیرد.

پیاده سازی Parcelable

رابط Parcelable متدها را به تمامی کلاس هایی که مایل به جابجایی بین اکتیویتی ها هستید، می افزاید.  برای این مثال نگاهی به نحوه پیاده سازی Parcelable در یک کلاس ساده می اندازیم، ایده کلی این است که وقتی یک ویژگی در لیست ویو را انتخاب می کنید، به ویوی جزئیات گسترده تر جهت دریافت اطلاعات بیشتر هدایت شوید.blog_21540_1

ساخت یک کلاس Property

اول از همه باید یک کلاس بسازید که تمامی اطلاعات درباره هر ویژگی را در خود نگه دارد، کار را با افزودن کدهای زیر به یک فایل کلاس جدید در پروژه آغاز کنید.

public class Property implements {

//property basics

private int streetNumber;

private String streetName;

private String suburb;

private String state;

private String description;

private String image;

private Double price;

private int bedrooms;

private int bathrooms;

private int carspots;

private Boolean featured;

//main constructor

public Property(int streetNumber, String streetName, String suburb, String state, String description, Double price, String image, int bedrooms, int bathrooms, int carspots, Boolean featured){

this.streetNumber = streetNumber;

this.streetName = streetName;

this.suburb = suburb;

this.state = state;

this.description = description;

this.price = price;

this.image = image;

this.bedrooms = bedrooms;

this.bathrooms = bathrooms;

this.carspots = carspots;

this.featured = featured;

}

//getters

public int getStreetNumber() { return streetNumber; }

public String getStreetName() {return streetName; }

public String getSuburb() {return suburb; }

public String getState() {return state; }

public String getDescription() {return description; }

public Double getPrice() {return price; }

public String getImage() { return image; }

public int getBedrooms(){ return bedrooms; }

public int getBathrooms(){ return bathrooms; }

public int getCarspots(){ return carspots; }

public Boolean getFeatured(){return featured; }

}

کلاس شامل مجموعه ای از ویژگی ها، توابع getter و یک سازنده برای ساخت آبجکت منفرد از کلاس می باشد.

افزودن رابط Parcelable

جایگذاری رابط مهم ترین بخش می باشد، تعریف کلاس را مطابق زیر عوض کنید:

public class Property implements Parcelable {

...

}

متدهای زیر را داخل کلاس اضافه کنید، در ادامه نحوه عملکرد هریک شرح داده خواهد شد.

//write object values to parcel for storage

public void writeToParcel(Parcel dest, int flags){

//write all properties to the parcle

}

//constructor used for parcel

public Property(Parcel parcel){

//read and set saved values from parcel

}

//creator - used when un-parceling our parcle (creating the object)

public static final Parcelable.Creator<Property> CREATOR = new Parcelable.Creator<Property>(){

@Override

public Property createFromParcel(Parcel parcel) {

return new Property(parcel);

}

@Override

public Property[] newArray(int size) {

return new Property[0];

}

};

//return hashcode of object

public int describeContents() {

return hashCode();

}

Parcelable نیازمند این کد برای انجام عملیات می باشد، در حقیقت وظیفه آن مدیریت فرآیند کپی داده های آبجکت به یک Parcel برای انتقالات بین اکتیویتی ها و ساخت مجدد آبجکت در سمت دیگر می باشد.

متد نوشتن – writeToParcel

در این متد تمامی ویژگی های کلاس را به parcel جهت آماده سازی برای انتقال اضافه می کنید و از متد های write جهت اضافه کردن هریک از ویژگی ها بهره می گیرید.

//write object values to parcel for storage

public void writeToParcel(Parcel dest, int flags){

dest.writeString(streetName);

dest.writeString(suburb);

dest.writeString(state);

dest.writeString(description);

dest.writeString(image);

dest.writeInt(streetNumber);

dest.writeValue(featured);

dest.writeDouble(price);

dest.writeInt(bedrooms);

dest.writeInt(bathrooms);

dest.writeInt(carspots);

}

نکات:

- ترتیب نوشتن مقادیر اهمیت دارد و در دریافت این مقادیر باید به همان ترتیبی که آنها را نوشته اید، عمل کنید.

- چنانچه مایل به ارسال مقادیر بولین مانند ویژگی featured هستید، باید از writeValue استفاده کرده و سپس در سمت دیگر آن را به بولین تبدیل کنید، زیرا هیچ متد نیتیوی جهت افزودن بولین وجود ندارد.

متد خواندن – Property

این متد سازنده است و در زمان دریافت اکتیویتی صدا زده می شود و در این مرحله باید به دریافت مقادیر بپردازید.

زمانی که اکتیویتی دوم متد getParcelableExtra از آبجکت intent را صدا می زند تا فرآیند شروع شود، این سازنده مقادیر را می گیرید و ویژگی های هر آبجکت را تعیین می کند.

//constructor used for parcel

public Property(Parcel parcel){

streetName = parcel.readString();

suburb = parcel.readString();

state = parcel.readString();

description = parcel.readString();

image = parcel.readString();

streetNumber = parcel.readInt();

featured = (Boolean) parcel.readValue(null);

price = parcel.readDouble();

bedrooms = parcel.readInt();

bathrooms = parcel.readInt();

carspots = parcel.readInt();

}

در این مرحله آبجکت با داده ها پر می شود.

چنانچه از آبجکت منحصر به فرد خود استفاده می کنید، نام تابع باید با نام کلاسی که ساخته اید مطابقت داشته باشد، برای نمونه person ،animal ،place، نام باید مطابق با نام کلاس باشد.

متد سازنده

Parcelable نیازمند این متد برای بایند کردن بخش ها با یکدیگر است و متد createFromParcel کل آبجکت پر شده را برمی گرداند.

//used when un-parceling our parcel (creating the object)

public static final Parcelable.Creator<Property> CREATOR = new Parcelable.Creator<Property>(){

@Override

public Property createFromParcel(Parcel parcel) {

return new Property(parcel);

}

@Override

public Property[] newArray(int size) {

return new Property[0];

}

};

سایر متدها – describeContents

این متد عملیات زیادی را به انجام نمی رساند.

//return hashcode of object

public int describeContents() {

return hashCode();

}

شروع Intent در اکتیویتی اول

در داخل اکتیویتی اول آبجکت intent خود را ساخته و از متد putExtra جهت اضافه کردن کل کلاس بهره بگیرید. تنها در صورتی که رابط Parcelable را به درستی جایگذاری کرده باشید، این متد کار کرده و Parcelable عملیات serialize کردن آبجکت را آغاز می نماید.

Intent intent = new Intent(MainActivity.this, DetailActivity.class);

intent.putExtra("Property", property);

startActivity(intent);

در صورتی که عملیات به درستی انجام شود، اکتیویتی دوم باز می شود. در این مرحله باید مطمئن شوید که اکتیویتی به فایل مانیفست شما اضافه شده است.

دریافت مقادیر در اکتیویتی دوم

هم اکنون در اکتیویتی دوم هستید و باید آبجکت intent را گرفته و کلاس property را که به یک parcel تبدیل شده، استخراج نمایید. پس از انجام این کار می توانید متدهای استاندارد را فراخوانی کرده و داده هایی مانند نام، قیمت و توضیحات را بگیرید.

//collect our intent

Intent intent = getIntent();

Property property = intent.getParcelableExtra("Property");

//now collect all property values

String streetName = property.getStreetName();

Integer streetNumber = property.getStreetNumber();

String suburb = property.getSuburb();

String state = property.getState();

String description = property.getDescription();

Double price = property.getPrice();

Integer bedrooms = property.getBedrooms();

Integer bathrooms = property.getBathrooms();

Integer carspots = property.getCarspots();

String image = property.getImage();

Integer imageID = this.getResources().getIdentifier(image, "drawable", this.getPackageName());

String address = streetNumber + " " + streetName + ", " + suburb + ", " + state;

ارسال Parcel

همانطور که مشاهده می کنید، برای راه اندازی و کار با parcelable نیازمند انجام کارهای اضافه هستید، اما قطعا نتیجه ای که دریافت می کنید ارزشمند است.

شما می توانید کل آبجکت ها را از یک اکتیویتی به دیگری منتقل کرده و تمامی متدها و قابلیت های کلاس را حفظ کنید. این عملکرد برای شرایطی که دارای یک متد پیچیده هستید که تمامی داده های شما را منتقل می سازد، بسیار کاربردی خواهد بود.

دیگر نیازی به یادآوری اسامی مختلف که به طور معمول به آبجکت intent به عنوان داده های اضافی ارسال می کنید نیست. برای مثال

String streetName = intent.getStringExtra("streetName");

شما می توانید آبجکت را گرفته و کار را ادامه دهید.

این فرآیند سریع و بهینه است و انجام آن سریع تر از استفاده از عملکرد serialize جاوا می باشد.

 

https://www.sitepoint.com برگرفته از

 

اینها را هم بخوانید

نظرات کاربران

  1. avatar
    حامد
    سلام آیا روش putExtra محدودیتی از نظر ارسال تعداد عناصر ارسالی داره ؟ اگه نداره بهتر نیست از همین روش putExtra استفاده کنیم ؟ روش Parcelable فقط انگار کار رو پیچیده تر کرده

    به این نظر پاسخ دهید
    1. واننی منصوریان
      واننی منصوریان (ادمین)
      با سلام دوست گرامی نوع ارسال در putExtra محدود است، مثل ارسال کلاس و لیست. Parcelable کمی پیچیده تر بوده اما از انعطاف بیشتری برخوردار است. موفق باشید

      به این نظر پاسخ دهید