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
Calculating the Angle Between a Line and the X-Axis
Java: Need Some Way to Shorten This Code
Android How to Sort JSONarray of JSONobjects
How to Ask Permission to Access Gallery on Android M.
What Is the Use of Memoryfile in Android
Android Java.Net.Unknownhostexception: Host Is Unresolved (Strategy Question)
How to Highlight Multiple Words in Edittext
How to Make Burst Mode Available to Camera
Android Getintent().Getextras() Returns Null
Android 6.0 (Marshmallow): How to Play Midi Notes
How to Override the Cipherlist Sent to the Server by Android When Using Httpsurlconnection
Intellij Build Error Context Mismatch
How to Fix Install_Parse_Failed_Manifest_Malformed in My Android Application
Theme.Appcompat.Light.Darkactionbar - No Resource Found
Using Serviceloader on Android
Android Webview Always Returns Null for JavaScript Getelementbyid on Loadurl