Updated on Nov 29, 2016 - added information on EventBus sticky
Assume we have a simple POJO which contains multiple information
public class POJO
{
public int integer;
public String string;
public Boolean bool;
public Float f;
public POJO(int integer, String string, Boolean bool, Float f)
{
this.integer = integer;
this.string = string;
this.bool = bool;
this.f = f;
}
// getters and setters
}
1. Normal intent
To pass data via an intent, use putExtra()
in the intent.
Passing single variable to an activity, use this method.
Intent intent = new Intent(context, MyActivity.class);
intent.putExtra("keyName","value");
intent.putExtra("keyName2", 2);
startActivity(intent);
To retrieve this data in the next Activity,
String data = getIntent().getExtras().getString("keyName");
int data2 = getIntent().getExtras().getInt("keyName2", 0);
Alternatively, with null checking technique (recommended):
Bundle extras = getIntent().getExtras();
if (extras != null) {
String value = extras.getString("keyName");
int data2 = extras.getInt("keyName2", 0);
}
2. Using Serializable
Serializable is a standard Java interface. You simply mark a class Serializable by implementing the interface, and Java will automatically serialize it in certain situations 1.
Serializable - close to zero boilerplate, but it is the slowest approach and also requires hard-coded strings when pulling values out the intent (non-strongly typed).2
Make our POJO class implements Serializable
public class POJO implements Serializable
{
public int integer;
public String string;
public Boolean bool;
public Float f;
public POJO(int integer, String string, Boolean bool, Float f)
{
this.integer = integer;
this.string = string;
this.bool = bool;
this.f = f;
}
}
Sending our POJO to another activity
Intent intent = new Intent(context, MyActivity.class);
intent.putExtra("myPojoKey", new POJO(1, "2", true, 3.0f));
startActivity(intent);
Receiving our POJO intent
Bundle extras = getIntent().getExtras();
if (extras != null) {
POJO pojoObject = extras.getSerializableExtra("myPojoKey");
}
3. Using Parcelable
Parcelable is an Android specific interface where you implement the serialization yourself. It was created to be far more efficient that Serializable, and to get around some problems with the default Java serialization scheme. 1
Parcelable - fast and Android standard, but it has lots of boilerplate code and requires hard-coded strings for reference when pulling values out the intent (non-strongly typed). 2
Make our POJO implements Parcelable
Protip: In Android Studio IDE, this class can easily created by generating the boilerplate code.
public class POJO implements Parcelable {
public int integer;
public String string;
public Boolean bool;
public Float f;
public POJO(int integer, String string, Boolean bool, Float f) {
this.integer = integer;
this.string = string;
this.bool = bool;
this.f = f;
}
//used to deflate the POJO
//before sending to destination activity
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeStringArray(new String[] {
String.valueOf(this.integer),
this.string,
String.valueOf(this.bool),
String.valueOf(this.f)
});
}
//used to inflate the POJO once it has
//reached its destination activity
public POJO(Parcel in) {
String[] data = new String[4];
in.readStringArray(data);
this.integer = Integer.parseInt(data[0]);
this.string = data[1];
this.bool = Boolean.parseBoolean(data[2]);
this.f = Float.parseFloat(data[3]);
}
//method on the interface
@Override
public int describeContents() {
return 0;
}
//More boilerplate
//Failure to add this results in the following exception
//"android.os.BadParcelableException: Parcelable protocol
//requires a Parcelable.Creator object called CREATOR on class"
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public POJO createFromParcel(Parcel in) {
return new POJO(in);
}
public POJO[] newArray(int size) {
return new POJO[size];
}
};
}
Sending our POJO to another activity
Similarly,
Intent intent = new Intent(context, MyActivity.class);
intent.putExtra("myPojoKey", new POJO(1, "2", true, 3.0f));
startActivity(intent);
Receiving our POJO intent
Bundle extras = getIntent().getExtras();
if (extras != null) {
POJO pojoObject = extras.getParcelableExtra("myPojoKey");
}
4. Using EventBus
Event Bus - zero boilerplate, fastest approach, and does not require hard-coded strings, but it does require an additional dependency (although usually lightweight, ~40 KB). 2
More detailed explanation: http://www.andreas-schrade.de/2015/11/28/android-how-to-use-the-greenrobot-eventbus/
Creating our bus
Simply call this method in any line of your code to receive EventBus instance.
EventBus myEventBus = EventBus.getDefault();
Creating our event
Guess what, our POJO is our event.
We need to create a new model-like class to pass our event to a subscriber.
public class POJOEvent {
POJO pojo;
public POJOEvent(POJO pojo) {
this.pojo = pojo;
}
// getters and setters
}
Creating our sender
Sending data on the bus is as easy as fuck.
POJO myPojo = new POJO(1, "2", true, 3.0f);
EventBus.getDefault().post(new POJOEvent(myPojo));
Creating our subscriber (retriever)
1. Register the bus
Register inside onCreate()
, onStart()
, or onResume()
.
EventBus.getDefault().register(this); // this == your class instance
2. Unregister the bus
Read on why we need to unregister an instance: http://stackoverflow.com/a/31931742/996701
Unregister should happen inside onDestroy()
, onPause()
or onStop()
.
EventBus.getDefault().unregister(this);
3. Retrieving the event
// This method will be called when a POJO event is posted
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(POJOEvent event){
// your implementation
processEvent(event.getPojo());
}
Sticky Event
Some events carry information that is of interest after the event is posted.3
My personal use-case would be, how to replace setIntent
or avoiding our model class to implement Parcelable/Serializable. Whenever I want to pass a model class, EventBus can do this for you.
The process is similar like the above, only thing we have to do is to change .post()
to .postSticky()
, and in our subscriber method we would want to explicitly define that it is a sticky event.
Posting a sticky event:
EventBus.getDefault().postSticky(new POJOEvent(myPojo));
Subscribing a sticky event:
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(POJOEvent event){
processEvent(event.getPojo());
}