Introduction
We often need to pass data between Activities of an Android app. An easy way to do this is with Intent.putExtra()
, but if you have a lot of structured data to pass, Parcelable may be a better solution. In this post I'll show you how Parcelable makes it easy to serialize classes for sharing between Activities.
Why Parcelable?
Parcelable is an Android-only Interface. It allows developers to serialize a class so its properties are easily transferred from one activity to another. This is done by reading and writing of objects from Parcels, which can contain flattened data inside message containers.
Creating the Main Activity and Layout
Our main Activity will handle the collection of the book details. Let's start by setting up our onCreate
method.
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); //... } }
Next, open activity_main.xml to set up the view's layout and appearance. You will need two text entry fields and a button for submission.
It should look like this:
<?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>
Now open your main Activity and link the view fields to your activity. You'll have to do it inside your onCreate()
method, like this:
//... final EditText mBkTitle = (EditText) findViewById(R.id.title); final EditText mBkAuthor = (EditText) findViewById(R.id.author); Button button = (Button) findViewById(R.id.submit_button);
To finish off MainActivity
, you need to set up an onClickListener
. This will be called whenever the Submit button is pressed. When that happens, the details entered are to be collected and sent to the next activity.
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); } });
Here, you add an onClickListener
to the Button
instance you retrieved from your Activity layout. This code will be run whenever the Submit button is clicked.
Note that we simply pass the Book
instance to putExtra()
. As we'll see later, Parcelable takes care of serializing the book data to a string so it can be passed via the Intent.
Now that the main Activity is complete, we need to create our BookActivity
as well as the Book class to hold book info.
Create the Book Class
Let's create a Book
class to hold info about each book.
public class Book implements Parcelable { // book basics private String title; private String author; }
This class needs to implement Parcelable
. This will enable the passing of the data from MainActivity
to BookActivity
.
We'll also add some standard getter functions and a constructor to quickly create an instance of the class.
// 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; }
Write to the Parcel
The writeToParcel
method is where you add all your class data to the parcel. This is done in preparation for transfer. This method will be passed a Parcel instance which has a number of write methods that you can use to add each field to the parcel. Watch out: the order in which you write the data is important!
Here is how you do it.
// write object values to parcel for storage public void writeToParcel(Parcel dest, int flags) { dest.writeString(title); dest.writeString(author); }
Read Data Back From the Parcel
Just as the write method handles writing the data to be transferred, the constructor is used to read the transferred data back from the serialized Parcel. This method will be called on the receiving activity to collect the data.
Here's how it should look:
public Book(Parcel parcel) { title = parcel.readString(); author = parcel.readString(); }
The receiving Activity will get the data as a string, and will then call the getParcelableExtra
method to start the process of collecting the data. That will trigger the constructor we defined above, which will deserialize the data and create a new Book
instance.
Parcelable.Creator
To complete your Parcelable class, you need to create a Parcelable.Creator
instance and assign it to the CREATOR
field. The Parcelable API will look for this field when it needs to deserialize an instance of your class that has been passed to another component.
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]; } };
This binds everything together. Its job is simple—it generates instances of your Parcelable class from a Parcel
using the parcel data provided. The creator calls the constructor you defined above, passing it a Parcel
object, and the constructor initializes the class attributes.
If your Parcelable class will have child classes, you'll need to take some extra care with the describeContents()
method. This will let you identify the specific child class that should be created by the Parcelable.Creator
. You can read more about how this works on Stack Overflow.
Book Activity and Layout
Now we can complete our app with the book Activity. Go ahead and create a new empty activity called BookActivity
. Make the layout look like what I have below.
<?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>
In the activity_book.xml, you only need two TextView
widgets, which will be used to show the title and author of the books.
Now let's set up our activity. Your activity should already look like this:
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); } }
In this activity, you want to receive the data that was passed from your main Activity and display it on your views. Thus you will retrieve the instances of your TextView
using the id of the TextView
set in your layout.
TextView mBkTitle = (TextView) findViewById(R.id.bk_title); TextView mBkAuthor = (TextView) findViewById(R.id.bk_author);
Then, of course, you'll call getIntent()
because you will be retrieving data in this activity. The data you will be retrieving are collected from the Book class using getParcelableExtra()
. Next, you set the values of the TextViews
to the data you collected. Here is how it is done.
Intent intent = getIntent(); Book book = intent.getParcelableExtra("Book"); mBkTitle.setText("Title:" + book.getTitle()); mBkAuthor.setText("Author:" + book.getAuthor());
Build your application and launch it, and you should see the little beauty you have just built.
Conclusion
In this post, you've seen how you can easily move objects from one activity to another. You no longer have to retrieve each data field you passed to the Intent object separately, and you don't have to remember the name that you passed each field under. Not only that, but this process is faster than Java's serialize functionality.
In this tutorial, you have learned how to use Parcelable to pass data from one activity to another. You can dive deeper into Parcelable by checking the official documentation.
In the meantime, check out some of our other posts about Android app development!
- Android SDKAdding Physics-Based Animations to Android Apps
- Android SDKWhat Is the Android Activity Lifecycle?
- Android SDKHow to Monetize Your Android Apps With AdMob