Error with implementing Parcelable object - android

I'm kind of new to Android development.
I don't understand why the following code gives me a stackoverflowerror
Intent intent = new Intent(view.getContext(), MakeCall.class);
SipParcelable sipp = new SipParcelable(_sip);
intent.putExtra("sip", (Parcelable) sipp);
startActivity(intent);
Basically as soon as the startActivity(intent) fires, I get the following error:
I can get rid of the error by commenting out the third line with the putExtra() function.
I'm trying to pass my _sip object over to the MakeCall.class activity on another screen that's about to load up. I tried to follow the tutorial on how to implement a Parcelable class/object. Here's what my SipParcelable code looks like:
import com.myproject.library.SipService;
import android.os.Parcel;
import android.os.Parcelable;
public class SipParcelable implements Parcelable{
public SipService mData;
/* everything below here is for implementing Parcelable */
// 99.9% of the time you can just ignore this
public int describeContents() {
return 0;
}
// write your object's data to the passed-in Parcel
public void writeToParcel(Parcel out, int flags) {
out.writeValue(mData);
}
public SipParcelable(SipService sip)
{
mData = sip;
}
// Parcelling part
public SipParcelable(Parcel in){
mData = (SipService) in.readValue(SipService.class.getClassLoader());
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public SipParcelable createFromParcel(Parcel in) {
return new SipParcelable(in);
}
public SipParcelable[] newArray(int size) {
return new SipParcelable[size];
}
};
}
What am I doing wrong?

Your SipService class must implement parcelabe and modify how SipService object is read and written from/to pracel.
check this tutorial it might help you
http://shri.blog.kraya.co.uk/2010/04/26/android-parcel-data-to-pass-between-activities-using-parcelable-classes/
You can use serialisable too… But parcelable is faster and better
NOTE: all properties of an object (if the properties are objects) that implements parcelable, must also be parcelable as well.

Related

Is it possible to create a Parcelable Class that has an empty constructor?

I'm trying to use firestore recycler adapter with a parcelable class, but it needs to have an empty constructor.
My solution now is to create a regular class with an empty constructor and right after fetching the data, I'll map the objects into a parcelable copy.
But is it possible to create a Parcelable Class with an empty constructor? In Android Studio when I do right click -> Generate -> I see no secondary constructor option so I guess it's not possible, right?
Yes, it is possible. The Parcelable object will be serialized and deserialized without any problem.
In Android Studio when I do right click -> Generate -> I see no secondary constructor option so I guess it's not possible, right?
No, the fact that it doesn't appear as suggestion in Android Studio code completion feature doesn't mean it is not possible.
Taking as a reference the Parcelable implementation from Android documentation. You should then need to add an empty constructor. Just write the code, don't use code generator.
public MyParcelable(){
}
The class then should look like this:
public class MyParcelable implements Parcelable {
private int mData;
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mData);
}
public static final Parcelable.Creator<MyParcelable> CREATOR
= new Parcelable.Creator<MyParcelable>() {
public MyParcelable createFromParcel(Parcel in) {
return new MyParcelable(in);
}
public MyParcelable[] newArray(int size) {
return new MyParcelable[size];
}
};
private MyParcelable(Parcel in) {
mData = in.readInt();
}
public MyParcelable(){
}
}

How to pass array or arraylist by intent which has unserializable data?

What I want to do is passing DataModel array between Activity by Intent.
DataModel class has Bitmap object and FirebaseVisionLabel object. I found many sites to implement this.
Many people said that DataModel class should implements Serializable or Parceable interface to pass DataModel[] or ArrayList<DataModel>.
So I tried, but the real problem was FirebaseVisionLabel class cannot be serializable. Also, I cannot modify that class because it is firebase library.
How can I pass DataModel array by intent??
Point
Want to pass array or arraylist of my own class by intent.
that class has unserializable object and I cannot modify.
how can I pass or deal with it?
Use Parceable. It works perfect
public class Test implements Parcelable
{
FirebaseVisionLabel firebaseVisionLabel;
String testString;
protected Test(Parcel in) {
testString = in.readString();
}
public static final Creator<Test> CREATOR = new Creator<Test>() {
#Override
public Test createFromParcel(Parcel in) {
return new Test(in);
}
#Override
public Test[] newArray(int size) {
return new Test[size];
}
};
public FirebaseVisionLabel getFirebaseVisionLabel() {
return firebaseVisionLabel;
}
public void setFirebaseVisionLabel(FirebaseVisionLabel firebaseVisionLabel) {
this.firebaseVisionLabel = firebaseVisionLabel;
}
public String getTestString() {
return testString;
}
public void setTestString(String testString) {
this.testString = testString;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(testString);
}
}
After that for passing data through intent
Test test = new Test();
test.setTestString("test");
test.setFirebaseVisionLabel(yourObject);
Intent intent = new Intent(this, BaseActivity.class);
intent.putExtra("key", test);
startActivity(intent);
Use the below code to get ArrayList data without Serialized or Parcelable:
Consider,
Intent intent = new Intent(this, your_second_class.class);
intent.putStringArrayListExtra("<your_name_here>", your_list_here);
startActivity(intent);
Then in your second class use:
Intent i = getIntent();
new_list = i.getStringArrayListExtra("<your_name_here>");
Hope it will work fine.
You may use Application class, which can be used in all the screen, activities.
So store array in Application class and used anywhere in app.
FirebaseVisionLabel doesn't have too many properties. You will need to serialize Label / Confidence /... (anything you care) yourself by creating your own VisionLabelParcelable class.
So far, there are not enough use cases to make ML Kit return a Parcelable FirebaseVisionLabel. Most apps should extract the info they are interested in and pass around if they want.

Should Parcel.writeSerializable be used in a Parcelable.writeToParcel?

I am new to android and am having a bit of trouble wrapping my head around the Parcelable interface.
I eventually found this:
https://stackoverflow.com/a/2141166/6647053
The point made in the above answer is that when passing an object to an activity, this:
intent.putExtra("object", parcelableObject);
performs much better than this:
intent.putExtra("object", serializableObject);
My question is:
Would there be any performance benefit to using a Parcel's read / write Serializable methods within the Parcelable (as opposed to just using a serializable object with intent.putExtra)? Why / Why not?
Example:
public class MyParcelable implements Serializable, Parcelable {
/* Some Custom Object Stuff Here */
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeSerializable(this);
}
public static final Parcelable.Creator<MyParcelable> CREATOR = new Parcelable.Creator<MyParcelable>() {
public MyParcelable createFromParcel(Parcel parcel) {
return parcel.readSerializable();
}
public MyParcelable[] newArray(int size) {
return new MyParcelable[size];
}
};
}
There is no benefit to writing this: parceling will be as slow as serializing.
In ordinary Java, Externalizable can perform better than Serializable, because you supply your own readExternal(ObjectInput in) and writeObject(ObjectOutput out) in which you are expected to manually serialize your fields instead of relying on the JVM to introspect and automatically do it for you. Android's Parcelable serves a similar purpose.

Parcelable error sending object from one to another activity

I cant resolve problem when i sending my object "filmovi" to another activity i got a error. when i was tried to send another object "korisnik" it works without any problem.
Error
FATAL EXCEPTION: main
java.lang.ClassCastException: ba.fit.kino.model.filmovi cannot be cast to android.os.Parcelable
Sending from activity
filmovi Film = ((filmovi)lstView.getItemAtPosition(position));
Intent intent = new Intent(getApplicationContext(), RezervacijaActivity.class)
intent.putExtra("Rezervacija", Film);
startActivity(intent);
Reciving in activity
filmovi filmoviRezervacija;
Bundle bundle = getIntent().getExtras();
if(bundle != null){
filmoviRezervacija = bundle.getParcelable.("Rezervacija");
}
I RESOLVE PROBLEM WITHT THIS:
public class filmovi implements Parcelable{......
public filmovi (Parcel source)
{
this.setFilmID(source.readInt());
this.setNaziv(source.readString());
this.setCijenaKarte(source.readFloat());
this.setSalaID(source.readInt());
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest,int flags)
{
dest.writeInt(this.filmID);
dest.writeString(this.naziv);
dest.writeFloat(this.cijenaKarte);
dest.writeInt(this.salaID);
}
public static final Parcelable.Creator<filmovi> CREATOR = new Parcelable.Creator<filmovi>() {
#Override
public filmovi createFromParcel(Parcel source) {
return new filmovi(source);
}
#Override
public filmovi[] newArray(int size) {
return new filmovi[size];
}
};
}
The reason is that your filmovi class is not parcelable
To make filmovi, or any class for that matter, parcelable, the class and all of its inner members should
implement the parcelable interface, and implement a writeToParcel method which loosely speaking
streams the class' content.
Here, for example
class MyClass implements parcelable {
private MyMemberDataClass data; <----- must also implement parcelable
void writeToParcel(Parcel dest, int flags) {...}
}
It is not enough that MyClass will implement parcelable.
MyMemberDataClass (i.e. the inner member class) must do so as well.
This may bet complicated. And in many cases it is also not really necessary...
instead, consider using an activity-parameters static object to which you will pass all of
your activity's required params without the need to parcel them!:
filmovi Film = ((filmovi)lstView.getItemAtPosition(position));
Intent intent = new Intent(getApplicationContext(), RezervacijaActivity.class)
RezervacijaActivityParams.setValue(Film); <--------------- instead of putExtra()
startActivity(intent);
Where:
class RezervacijaActivityParams {
private static filmovi Film;
public static void getValue(filmovi f) { Film = f; }
public static filmovi getValue() { return Film; }
}
and in RezervacijaActivity's onCreate:
class RezervacijaActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
filmovi = RezervacijaActivityParams.getValue();
RezervacijaActivityParams.setValue(null); <---------- clear static data
}
}
Note, and this is also an answer to kcoppock's comment, that it is a good practice for
your activity to clear the static data immediately after retrieving it.
EDIT: As kcoppock mentioned, you can't place Objects into Intents as extras unless they're serializable or parcelable. Therefore, your Film class will need to implement one of those. I've only ever added native types (int, etc.) to Intents, so I did not know this. Something to watch out for!
As an aside, it's good practice to extract your key strings to static final values. That ensures that the same string ends up in each location you use it.

Extending a class that implements Parcelable

I have a class, we'll call it class A, that implements Parcelable.
I have a second class, we'll call it class B, that extends class A.
My question is:
How do I write class B's member variables to the Parcel and then write it's parent class's (ie: class A's) member variables to the Parcel (and, subsequently, read them in)?
Is there some nifty trick to not needing to rewrite class A's Parcel code? Or do I just need to rewrite the Parcel code in class A and add additional code for class B's member variables?
How do I write class B's member variables to the Parcel and then write it's parent class's (ie: class A's) member variables to the Parcel
Class B overrides writeToParcel() from Class A, chaining to the superclass and also adding its own objects to the Parcel.
(and, subsequently, read them in)?
Class B implements public static final Parcelable.Creator<MyParcelable> CREATOR in such a way that it can let both classes read their stuff in. If you take the approach of creating a constructor on Class B that takes a Parcel as a constructor parameter, just chain to the superclass constructor (to let Class A do its work), then read Class B's data.
The key will be to do them both in the same order. If you intend to let Class A read its data first, Class A must write its data first.
Is there some nifty trick to not needing to rewrite class A's Parcel code?
Inheritance and chaining to the superclass.
Adding an example, the marked answer is indeed correct, but something more visual seems more suitable for this situation:
This would be the supper class:
public class BasePojo implements Parcelable {
private String something;
//what ever other constructor
//getters and setters
protected BasePojo(Parcel in) {
something = in.readString();
}
public static final Creator<BasePojo> CREATOR = new Creator<BasePojo>() {
#Override
public BasePojo createFromParcel(Parcel in) {
return new BasePojo(in);
}
#Override
public BasePojo[] newArray(int size) {
return new BasePojo[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(something);
}
}
And then this would be the child class:
public class ChildPojo extends BasePojo implements Parcelable {
private int somethingElse;
//what ever other constructor
//getters and setters
protected ChildPojo(Parcel in) {
super(in);
somethingElse = in.readInt();
}
public static final Creator<ChildPojo> CREATOR = new Creator<ChildPojo>() {
#Override
public ChildPojo createFromParcel(Parcel in) {
return new ChildPojo(in);
}
#Override
public ChildPojo[] newArray(int size) {
return new ChildPojo[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
super.writeToParcel(parcel, i);
parcel.writeInt(somethingElse);
}
}
The marked answer provides a very good explanation, calling super is the key.
It is a little complex, but the trick is to use Reflection to get the types of subclass's members and to sort the members so that you can read and write the data back in the same exact order using the proper types.
I have implemented the solution for class A here: https://github.com/awadalaa/Android-Global-Parcelable
so now you can make any class parcelable by simply extending this class.

Categories

Resources