What Will I Learn?
- Create Model Object in Java
- Serialize Model Class using Parcel
- Passing data objects between activities
Requirements
- Android Studio
- Java programming language
- Gradle dependency
- Custom serialization using ParcelPropertyConverter
Difficulty
- Basic
Tutorial Contents
Parceler is a code generation library that generates the Android Parcelable boilerplate source code. Parceler makes it easy to transfer to data from one activity to another and so on fragment though. Because, when we are developing an Android application usually we always need data when starting a new activity. Serialization is a marker interface, which implies the user cannot marshal the data according to their requirements. Therefore, we use the parceler and don't have too much code for doing such things like passing data object, data object list, etc.
Integrate project via gradle
First of all we need to define this library to the project first. We will add the dependencies via gradle.
Click the build.gradle (Module:app) one. Add this line to dependencies section.
compile 'org.parceler:parceler-api:1.1.9'
annotationProcessor 'org.parceler:parceler:1.1.9'
Once you've done, click the sync now button.
Creating The Model Class
We need to define our model first. I create some properties using public fields because when we use private fields, the default field serialization strategy as it will incur a performance penalty due to reflection . Of course you can add or change properties depends on your requirements.
public class Task {
public String id;
public String title;
public String detail;
public String image;
public int status;
public User user;
}
After we create the model, don't forget to add the public constructor with no arguments for the annotation library. Once it's done, add the Parcel annotation above of the class to make this model class parcelable.
package com.professional.andri.taskmanager.model;
import org.parceler.Parcel;
/**
* Created by Andri on 19/11/2017.
*/
@Parcel
public class Task {
public String id;
public String title;
public String detail;
public String image;
public int status;
public User user;
public Task(){
}
}
Passing data between activities
Next, we want to pass a data object from activity to another activity. Now, in your onCreate method in a activity. Create this task object.
Task task = new Task();
task.title = "Fix payment bugs";
task.detail = "When the customer click the payment method, it display wrong information. Please fix it";
Notice that this is a instantiation of a task object. Now, let's continue. We create the intent and put the task using putExtra and use the Parcels.wrap
method. Write these codes. Notice that we put the key "task" that we will use later.
Intent intent = new Intent(this, TaskListActivity.class);
intent.putExtra("task", Parcels.wrap(task));
startActivity(intent);
To make sure that you have the object instantiated well, you can log it like using this line.
Log.d("TAG", "TASK TITLE " + task.title + "TASK DETAIL " + task.detail);
After that, go to the logcat and see the messages you have logged before.
Notice the highlighted row, that is log that we are printing. Or you can check via debugger, give a line a break point then press the bug icon.
After done, we can go to another activity that we put the intent with parcelable earlier. I assume this is TaskListActivity in this post and in onCreate method. We retrieve that value by unwrapping the parcels using the key that we provide before start the activity to this intent. We will log to make sure the data pass to this activity properly. Write down these codes.
Task task = Parcels.unwrap(getIntent().getParcelableExtra("task"));
Log.d("TAGGG", "PARCEL: TASK TITLE: " + task.title + " TASK DETAIL " + task.detail);
Check the log. You will see something looks like this.
Custom serialization using ParcelPropertyConverter
In some specific case like List or RealmList, we cannot just directly give annotation become parceler. We need something called ParcelPropertyConverter. Write down this class first. This class is used to convert a RealmList overriding the fromParcel and toParcel method.
package com.professional.andri.taskmanager.converter;
import android.os.Parcelable;
import org.parceler.Parcels;
import org.parceler.TypeRangeParcelConverter;
import io.realm.RealmList;
import io.realm.RealmObject;
/**
* Created by Andri on 2/25/2018.
*/
public class RealmListParcelConverter implements TypeRangeParcelConverter<RealmList<? extends RealmObject>,
RealmList<? extends RealmObject>>{
private static final int NULL = -1;
@Override
public void toParcel(RealmList<? extends RealmObject> input, android.os.Parcel parcel) {
parcel.writeInt(input == null ? NULL : input.size());
if (input != null) {
for (RealmObject item : input) {
parcel.writeParcelable(Parcels.wrap(item), 0);
}
}
}
@Override
public RealmList fromParcel(android.os.Parcel parcel) {
int size = parcel.readInt();
RealmList<Object> list = new RealmList<>();
for (int i=0; i<size; i++) {
Parcelable parcelable = parcel.readParcelable(getClass().getClassLoader());
list.add(Parcels.unwrap(parcelable));
}
return list;
}
}
After that, go to the model we created earlier or you can create a new one. In this case i create a new model class call UserRealm that extends RealmObject and give additional implementation, value and analyze because this is not a basic model class. Add this annotation to the realm list @ParcelPropertyConverter(RealmListParcelConverter.class)
. Your class should look like something like this.
package com.professional.andri.taskmanager.realm;
import com.professional.andri.taskmanager.converter.RealmListParcelConverter;
import org.parceler.Parcel;
import org.parceler.ParcelPropertyConverter;
import io.realm.RealmList;
import io.realm.RealmObject;
import io.realm.RealmResults;
import io.realm.UserRealmRealmProxy;
import io.realm.annotations.PrimaryKey;
/**
* Created by Andri on 2/23/2018.
*/
@Parcel(implementations = { UserRealmRealmProxy.class },
value = Parcel.Serialization.FIELD,
analyze = { UserRealm.class })
public class UserRealm extends RealmObject {
@PrimaryKey
private long id;
private String level;
private String name;
private String username;
private String password;
@ParcelPropertyConverter(RealmListParcelConverter.class)
private RealmList<TaskRealm> tasks;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public RealmList<TaskRealm> getTasks() {
return tasks;
}
public void setTasks(RealmList<TaskRealm> tasks) {
this.tasks = tasks;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Run again and test the log on your own. It should pass the data correctly. Congratulation, now you can pass datas between activity and using converter to configure more. This kind of passing data is often used in Android development. Thank you for reading this post.
Posted on Utopian.io - Rewarding Open Source Contributors
Thank you for the contribution. It has been approved.
You can contact us on Discord.
[utopian-moderator]
Hey @andrixyz I am @utopian-io. I have just upvoted you!
Achievements
Suggestions
Get Noticed!
Community-Driven Witness!
I am the first and only Steem Community-Driven Witness. Participate on Discord. Lets GROW TOGETHER!
Up-vote this comment to grow my power and help Open Source contributions like this one. Want to chat? Join me on Discord https://discord.gg/Pc8HG9x