What Is Parcelable in Android

What is Parcelable in android

This concept is called Parcelable

A Parcelable is the Android implementation of the Java Serializable. It assumes a certain structure and way of processing it. This way a Parcelable can be processed relatively fast, compared to the standard Java serialization.

To allow your custom object to be parsed to another component they need to implement the android.os.Parcelable interface. It must also provide a static final method called CREATOR which must implement the Parcelable.Creator interface.

The code you have written will be your model class.

You can use Parcelable in Activity like :

intent.putExtra("student", new Student("1")); //size which you are storing

And to get this object :

Bundle data = getIntent().getExtras();
Student student = (Student) data.getParcelable("student");

Here Student is a model class name. replace this with yours.

In simple terms Parcelable is used to send a whole object of a model class to another page.

In your code this is in the model and it is storing int value size to Parcelable object to send and retrieve in other activity.

Reference :

Tutorial 1

Tutorial 2

Tutorial 3

Parcelable and inheritance in Android

Here is my best solution, I would be happy to hear from somebody that had a thought about it.

public abstract class A implements Parcelable {
private int a;

protected A(int a) {
this.a = a;
}

public void writeToParcel(Parcel out, int flags) {
out.writeInt(a);
}

protected A(Parcel in) {
a = in.readInt();
}
}

public class B extends A {
private int b;

public B(int a, int b) {
super(a);
this.b = b;
}

public static final Parcelable.Creator<B> CREATOR = new Parcelable.Creator<B>() {
public B createFromParcel(Parcel in) {
return new B(in);
}

public B[] newArray(int size) {
return new B[size];
}
};

public int describeContents() {
return 0;
}

public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(b);
}

private B(Parcel in) {
super(in);
b = in.readInt();
}
}

Android - polymorphism and Parcelable

I wrote this little fragment and loaded it into a FrameLayout in the main activity to check - and I got positive results (the rebuilt object from the parcel was of type DerivedClass although the references of the object were all of type ObjectClass).

import android.app.Fragment;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class Fragment2 extends Fragment {

public ObjectClass obj;

public static final String OBJECT_KEY = "Object key";

public static Fragment2 newInstance(){
Fragment2 fragment = new Fragment2();
Bundle args = new Bundle();
ObjectClass obj = new DerivedClass(); //a DerivedClass object
//referenced by an ObjectClass reference
args.putParcelable(OBJECT_KEY, obj);
fragment.setArguments(args);
return fragment;
}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main2, container, false);
if (savedInstanceState == null){
Bundle args = getArguments();
obj = args.getParcelable(OBJECT_KEY); //without supplying the ClassLoader
((TextView)view.findViewById(R.id.section_label)).setText(obj.getTitle());
//The text that is displayed is: "Child class"!
}
return view;
}

//The parent class
public static class ObjectClass implements Parcelable {
String title = "Parent class";

public String getTitle(){
return title;
}

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {

}

public static final Creator<ObjectClass> CREATOR = new Creator<ObjectClass>() {
@Override
public ObjectClass createFromParcel(Parcel source) {
return new ObjectClass();
}

@Override
public ObjectClass[] newArray(int size) {
return new ObjectClass[size];
}
};
}

//The child class
public static class DerivedClass extends ObjectClass {
String title2 = "Child class";

public String getTitle() {
return title2;
}

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {

}

public static final Parcelable.Creator<DerivedClass> CREATOR = new Parcelable.Creator<DerivedClass>() {
@Override
public DerivedClass createFromParcel(Parcel source) {
return new DerivedClass();
}

@Override
public DerivedClass[] newArray(int size) {
return new DerivedClass[size];
}
};
}
}

And in the main activity, in onCreate(Bundle) method:

getFragmentManager().beginTransaction().replace(R.id.frameContainer, Fragment2.newInstance()).commit();

My thoughts that led me to this check: As android must figure out what class to use when recreating the object from the parcel (which CREATOR to use), I figured it must store this additional information together with the specified information ( specified in the writeToParcel(Parcel, int) method) when putting it into the bundle. To determine this class I thought it can either use the reference's type or use the object itself (e.g. using getClass() on it). If it uses the object type itself that of course means polymorphism is possible. From my check above it looks like that is indeed the case.

Conclusion and a guess for your example:
I think for your example, try not to explicitly pass the ClassLoader. Pass null. From the documentation for the parameter of Parcel#readParcelable(ClassLoader):

ClassLoader: A ClassLoader from which to instantiate the Parcelable object, or null for the default class loader.

I didn't try it with your configuration, so I'm not sure it will work in the same way as in my example. Specifically, I'm not sure whether Parcel#readParcelable(ClassLoader=null) actually works in the same manner as Bundle#getParcelable(String). but if my rationale is right - it should (I assume Bundle#getParcelable(String) uses the default ClassLoader as long as Bundle#setClassLoader(ClassLoader) wasn't called).

Please comment and let me know if it worked for you.

Android: Can I pass an array of Parcelable objects? Do I need to create a wrapper object?

Do something like this to write an array list into Parcelable:

public class Task implements Parcelable {
List<Task> taskList;

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(taskList);
...
}

@SuppressWarnings("unchecked")
private Task(Parcel in) {
taskList = (List<Task>) in.readValue(List.class.getClassLoader());
...
}
}

It 100% works for me.

Passing custom class objects using parcelable

In your comment you say that CustomClass is made of 4 integer variables. You could therefore do something like this:

class A implements Parcelable {

private CustomClass B;

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(B.getFirst());
dest.writeInt(B.getSecond());
dest.writeInt(B.getThird());
dest.writeInt(B.getFourth());
}

private A(Parcel in) {
B = new CustomClass();
B.setFirst(dest.readInt());
B.setSecond(dest.readInt());
B.setThird(dest.readInt());
B.setFourth(dest.readInt());
}
}


Related Topics



Leave a reply



Submit