Today, I'm talking about Intents and passing data by Intent in Android development.
Intent overview
An intent is an abstract description of an operation to be performed. It can be used with startActivity to launch an Activity, broadcastIntent to send it to any interested BroadcastReceiver components, and startService(Intent) or bindService(Intent, ServiceConnection, int) to communicate with a background Service.
An Intent provides a facility for performing late runtime binding between the code in different applications. Its most significant use is in the launching of activities, where it can be thought of as the glue between activities. It is basically a passive data structure holding an abstract description of an action to be performed.
Sending data via Intent
We can send data via Intent only following types:
int, int[]
double, double[]
char, char[]
float, float[]
byte, byte[]
long, long[]
short, short[]
String, String[]
CharSequence, CharSequence[]
Parcelable, Parcelable[]
Serializable, Serializable[]
Bundle
When you want passing data of primitive type it's really easy.
Intent openDetailIntent = new Intent(MainActivity.this, DetailActivity.class);
openDetailIntent.putExtra(“NAME”, mNameEditText.getText.toString());
But if you want to pass custom object you must realise Parcelable
or Serializable
interface for your object.
Serializable
Serializability of a class is enabled by the class implementing the java.io.Serializable interface. Classes that do not implement this interface will not have any of their state serialized or deserialized. All subtypes of a serializable class are themselves serializable. The serialization interface has no methods or fields and serves only to identify the semantics of being serializable.
To allow subtypes of non-serializable classes to be serialized, the subtype may assume responsibility for saving and restoring the state of the supertype’s public, protected, and (if accessible) package fields. The subtype may assume this responsibility only if the class it extends has an accessible no-arg constructor to initialize the class’s state. It is an error to declare a class Serializable if this is not the case. The error will be detected at runtime.
During deserialization, the fields of non-serializable classes will be initialized using the public or protected no-arg constructor of the class. A no-arg constructor must be accessible to the subclass that is serializable. The fields of serializable subclasses will be restored from the stream.
Next source code show how to implement class with Serializable
interface:
public class Person implements Serializable {
private String name;
private String surname;
private int age;
public Person(String name, String surname, int age) {
this.name = name;
this.surname = surname;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Parcelable
Interface for classes whose instances can be written to and restored from a Parcel. Classes implementing the Parcelable interface must also have a non-null static field called CREATOR of a type that implements the Parcelable.Creator interface.
Next source code show how to implement class with Parcelable
interface:
public class Person implements Parcelable {
private String name;
private String surname;
private int age;
protected Person(Parcel in) {
name = in.readString();
surname = in.readString();
age = in.readInt();
}
public Person(String name, String surname, int age) {
this.name = name;
this.surname = surname;
this.age = age;
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person createFromParcel(Parcel in) {
return new Person(in);
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(surname);
dest.writeInt(age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Which interface is better for Java and/or Android development
If we will talk about Java development better way use Serializable
, because it's a standard Java interface. But if we talk about Android development better way use the Parcelable
interface, because this interface faster than Serializable
and optimised for Android OS.
Example of using each of interfaces
Parcelable
Put data to intent
Person person = new Person(
mName.getText().toString(),
mSurname.getText().toString(),
Integer.valueOf(mAge.getText().toString())
);
Intent openDetailIntent = new Intent(MainActivity.this, DetailActivity.class);
openDetailIntent.putExtra(DetailActivity.PERSON, person);
startActivity(openDetailIntent);
In this snipped of code mName
, mSurname
and mAge
are EditText's. DetailActivity.PERSON
it's a sting constant (public static final String PERSON = "person";
)
Get data from intent
private void loadDataFromIntent() {
if (getIntent().getExtras() != null) {
Person person = getIntent().getParcelableExtra(PERSON);
if (person != null) {
mName.setText(person.getName());
mSurname.setText(person.getSurname());
mAge.setText(String.valueOf(person.getAge()).toString());
}
}
}
In this snippet of code mName
, mSurname
, mAge
are TextView's.
Serializable
Put data to intent
Person person = new Person(
mName.getText().toString(),
mSurname.getText().toString(),
Integer.valueOf(mAge.getText().toString())
);
Intent openDetailIntent = new Intent(MainActivity.this, DetailActivity.class);
openDetailIntent.putExtra(DetailActivity.PERSON, person);
startActivity(openDetailIntent);
In this snipped of code mName
, mSurname
and mAge
are EditText's. DetailActivity.PERSON
it's a sting constant (public static final String PERSON = "person";
)
Get data from intent
private void loadDataFromIntent() {
if (getIntent().getExtras() != null) {<
Person person = (Person) getIntent().getSerializableExtra(PERSON);
if (person != null) {
mName.setText(person.getName());
mSurname.setText(person.getSurname());
mAge.setText(String.valueOf(person.getAge()).toString());
}
}
}
In this snippet of code mName
, mSurname
, mAge
are TextView's.