مبادله داده بین اکتیویتی ها با استفاده از Parcelable اندروید
مقدمه
مبادله داده بین اکتیویتی های اپلیکیشن اندروید اغلب مورد نیاز است و یکی از روش های ساده برای این کار استفاده از ()Intent.putExtra میباشد، اما اگر داده های ساختاربندی شده حجم زیادی داشته باشند، استفاده از Parcelable راه حل بهتری خواهد بود.
در این مطلب با نحوه استفاده از Parcelable برای اشتراک گذاری داده بین اکتیویتی ها آشنا خواهید شد، با ما همراه باشید.
Parcelable چیست؟
Parcelable یک رابط مختص اندروید است که توسعه دهندگان با استفاده از آن میتوانند یک کلاس را سریالایز نمایند، با این کار ویژگی های کلاس به راحتی از یک اکتیویتی به دیگری منتقل میشود. این کار با خواندن و نوشتن آبجکت ها از Parcelable ها صورت میپذیرد.
ساخت اکتیویتی اصلی و لی اوت
اکتیویتی اصلی (Main Activity) در مثال این مطلب آموزشی مجموعه ای از جزئیات کتاب ها میباشد. اول از همه متد onCreate را استفاده میکنیم.
package com.tutsplus.code.android.bookparcel;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//...
}
}
در مرحله بعد فایل activity_main.xml را باز کنید و لی اوت و ظاهر ویو را بسازید. به دو فیلد ورودی و یک دکمه برای ارسال نیاز خواهید داشت.
این ویو چیزی مشابه زیر میباشد:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_margin="5dp"
android:padding="5dp"
tools:context="com.tutsplus.code.android.bookparcel.MainActivity">
<EditText
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:padding="20dp"
android:textSize="15sp"
android:hint="Book Title"/>
<EditText
android:id="@+id/author"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:padding="20dp"
android:textSize="15sp"
android:hint="Book Author"/>
<Button
android:id="@+id/submit_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:text="Submit"/>
</LinearLayout>
حال اکتیویتی را باز کنید و فیلدهای ویو را به اکتیویتی لینک بدهید. این کار درون متد ()onCreate انجام میشود:
//...
final EditText mBkTitle = (EditText) findViewById(R.id.title);
final EditText mBkAuthor = (EditText) findViewById(R.id.author);
Button button = (Button) findViewById(R.id.submit_button);
در آخر لازم است یک onClickListener را هم به MainActivity بیفزاییم. این متد به محض کلیک روی دکمه Submit فراخوانی میشود و جزئیات وارد شده درباره کتاب جمع آوری شده و برای اکتیوتی بعدی ارسال میشود.
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Book book = new Book(mBkTitle.getText().toString(),
mBkAuthor.getText().toString());
Intent intent = new Intent(MainActivity.this, BookActivity.class);
intent.putExtra("Book", book);
startActivity(intent);
}
});
در این مرحله یک onClickListener به نمونه Button که از لی اوت اکتیویتی بازیابی کرده اید، اضافه کنید. این کد به محض کلیک شدن دکمه Submit به اجرا درمی آید.
توجه داشته باشید که نمونه اولیه Book را به ()putExtra ارسال کرده ایم. همانطور که بعدا میبینید، Parcelable داده های مرتبط را سریالایز میکند و میتوانید با استفاده از Intent آنها را ارسال کنید.
حال که اکتیویتی اصلی کامل شد، باید BookActivity را به همراه کلاس Book که شامل اطلاعات کتاب است بسازیم.
ساخت کلاس Book
یک کلاس Book میسازیم که اطلاعات هریک از کتاب ها را ذخیره میکند.
public class Book implements Parcelable {
// book basics
private String title;
private String author;
}
این کلاس باید Parcelable را اجرا کند تا بتواند داده ها را از MainActivity به BookActivity ارسال نماید.
برای ساخت سریع نمونه از کلاس از چند تابع getter استاندارد به همراه یک constructor استفاده میکنیم.
// main constructor
public Book(String title, String author) {
this.title = title;
this.author = author;
}
// getters
public String getTitle() { return title; }
public String getAuthor() { return author; }
عملیات نوشتن در Parcelable
در متد writeToparcel تمامی داده های کلاس به Parcel اضافه میشوند تا برای انتقال آماده شوند. این متد یک نمونه اولیه Parcel را که چندین متد نوشتن دارد ارسال میکند و میتوانید از این متدها برای افزودن هر فیلد به parcel استفاده کنید. توجه داشته باشید که ترتیب نوشتن داده ها مهم است.
در زیر نحوه انجام این کار نمایش داده شده است:
// write object values to parcel for storage
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(title);
dest.writeString(author);
}
خواندن داده از Parcel
درست مانند متد قبلی که عملیات نوشتن داده های مورد انتقال را انجام میدهد، Constructor نیز برای خواندن داده های منتقل شده از Parcel سریالایز شده مورد استفاده قرار میگیرد. این متد هنگام بازیابی اکتیویتی برای جمع آوری داده ها فراخوانی میشود.
در زیر نحوه انجام این کار را مشاهده میکنید:
public Book(Parcel parcel) {
title = parcel.readString();
author = parcel.readString();
}
اکتیویتی دریافتی، داده ها را به صورت یک رشته میگیرد و بعد متد getParcelLabelExtra را صدا میزند تا فرآیند جمع آوری داده را آغاز کند. این کار سبب فعال سازی constructor که کمی پیش تعریف کردیم میشود و داده ها دی سریالایز میشوند و یک نمونه اولیه جدید از Book ساخته میشود.
Parcelable.Creator
برای کامل کردن کلاس Parcelable باید یک نمونه اولیه Parcelable.Creator بسازید و آن را به فیلد CREATOR تخصیص دهید. Parcelable API هنگام دی سریالایز کردن یک نمونه اولیه از کلاس شما که به کامپوننت دیگری ارسال شده، به دنبال این فیلد میگردد.
public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() {
@Override
public Book createFromParcel(Parcel parcel) {
return new Book(parcel);
}
@Override
public Book[] newArray(int size) {
return new Book[0];
}
};
عملیات بسیار ساده است، تولید نمونه های اولیه از کلاس Parcelable از یک Parcel با استفاده از داده های Parcel که در اختیار دارد. سازنده، constructor را که قبلا تعریف کرده بودید صدا میزند و یک آبجکت Parcel را میفرستد و constructor ویژگی های کلاس را اینیشیالایز میکند.
اگر کلاس Parcelable شما کلاس های فرزند نیز داشته باشد، باید از متد ()describeContents هم استفاده کنید. بدین ترتیب میتوانید کلاس فرزند خاصی را که باید با استفاده از parcelable.Creator ساخته شود، شناسایی کنید.
اکتیویتی و لی اوت Book
در این مرحله میتوانیم اپلیکیشن را با اکتیویتی Book کامل کنیم. یک اکتیویتی خالی به نام BookActivity بسازید، لی اوت باید مشابه زیر باشد.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_margin="5dp"
android:padding="5dp"
tools:context="com.tutsplus.code.android.bookparcel.BookActivity">
<TextView
android:id="@+id/bk_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Book"
android:textSize="30sp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:padding="20dp"/>
<TextView
android:id="@+id/bk_author"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Author"
android:textSize="30sp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:padding="20dp"/>
</LinearLayout>
در فایل activity_book.xml تنها به دو ویجت TextViewنیاز دارید که برای نمایش عنوان و نویسنده کتاب ها استفاده میشود.
اکتیویتی باید مشابه زیر باشد:
package com.tutsplus.code.android.bookparcel;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class BookActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_book);
}
}
در این اکتیویتی شما میخواهید داده هایی را که از اکتیویتی اصلی ارسال شده، دریافت کنید و در ویوها نمایش دهید. از این رو باید نمونه های اولیه از TextView را با استفاده از آی دی TextView که در لی اوت شما ست شده، بازیابی کنید.
TextView mBkTitle = (TextView) findViewById(R.id.bk_title);
TextView mBkAuthor = (TextView) findViewById(R.id.bk_author);
پس از آن باید ()getIntent را صدا بزنید، زیرا باید در این اکتیویتی داده ها را بازیابی کنید. داده هایی که بازیابی میکنید، با استفاده از ()getPardelableExtra از کلاس Book جمع آوری میشوند. پس از آن مقادیر TextViews را برای داده های جمع آوری شده تعیین کنید. در زیر نحوه انجام این کار نمایش داده شده است.
Intent intent = getIntent();
Book book = intent.getParcelableExtra("Book");
mBkTitle.setText("Title:" + book.getTitle());
mBkAuthor.setText("Author:" + book.getAuthor());
اپلیکیشن را بیلد کرده و اجرا کنید و از چیزی که ساخته اید لذت ببرید!
جمع بندی
همانطور که دیدید، انتقال آبجکت ها از یک اکتیویتی به دیگری به سادگی صورت میپذیرد. دیگر نیازی نیست به صورت جداگانه هر فیلدی را که به آبجکت Intent فرستاده اید، بازیابی کنید. این فرآیند از عملیات سریالایز جاوا سریع تر است.
در این مطلب آموزشی با نحوه استفاده از Parcelable برای انتقال داده از یک اکتیویتی به دیگری آشنا شدید. برای کسب جزئیات بیشتر در این خصوص میتوانید به این لینک مراجعه کنید.