Parcelable error sending object from one to another activity - android

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.

Related

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.

Is it possible to put Activity in the parcel?

Below is the example of my Parcelable class. As you can see, I want to put activity in a Parcel, but how could I do that? I look into the source code of Activity, it is not Parcelable nor Serializable.
public class MyParcelable implements Parcelable {
private Activity mActivity;
private int mData;
private String mName;
#Override
public void writeToParcel(Parcel out, int flags) {
//out.writeX(mActivity);
out.writeInt(mData);
out.writeString(mName);
}
private MyParcelable(Parcel in) {
//mActivity = in.readX();
mData = in.readInt();
mName = in.readString();
}
public MyParcelable(Activity activity, int data, String name) {
mActivity = activity;
mData = data;
mName = name;
}
#Override
public int describeContents() {
return 0;
}
public static final Parcelable.Creator<MyParcelable> CREATOR
= new Parcelable.Creator<MyParcelable>() {
#Override
public MyParcelable createFromParcel(Parcel in) {
return new MyParcelable(in);
}
#Override
public MyParcelable[] newArray(int size) {
return new MyParcelable[size];
}
};
}
You can put anything in Parcel and take anything out of Parcel. But whether that "anything" will work afterwards will depend on variety of factors.
All Activity instances exist in close cooperation with Android's ActivityManager. Most of methods, that define Activity: startActivity(), finish(), restart(), setContentView(), getPackage() delegate to methods of ActivityManager, ViewManager, PackageManager, and other system services. These methods won't work after Activity is destroyed by system. Those methods also won't work if you instantiate Activity class without Android's "special sauce". While it is technically possible to instantiate an Activity class using reflection or JNI, those instances simple won't work.
This is what people mean, when they say that Activity is "managed by Android": it is basically driven by OS processes, and can not exist without communication with those processes. Fortunately, Android has a way to initiate such communication: an Intent. Replace this line:
private Activity mActivity;
with
private Intent mActivity;
And use the parcelized Intent to start the Activity once you receive it on other side. Of course, if you need more things than just Intent to get your Activity in usable shape, you will have to store those things alongside with Intent within your Parcelable.
This is not good idea to put activity to parcel. If you require to do this, probably your code is bad and you need to review the code to avoid this implementation.

Error with implementing Parcelable object

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.

How to share objects with other activities?

My program has a range of different class activities (basically different screens). In one activity I am creating multiple objects which I would then like to access in other activities.
How do I go about making these objects accessible to other activities within my program, in other words how do I share objects with other activities?
TIA
Mark
The first thing you need to resolve is the operation order. If activity A is the one with the shared objects, what would you do if activity B is run without activity A ever being initialized? Do remember that intents to start activities may come from everywhere, though, to be truthful, exiting with NULL pointer dereference is an acceptable response.
What I did when such a thing was necessary was to not have the shared objects part of the activity, but create a specific object for containing those. You can then store a static reference to that object inside the object, and return it via a static method:
public class GlobalParams {
private static reference;
public static GlobalParams getReference()
{
if( reference==NULL )
reference=new GlobalParams();
return reference;
}
}
I don't think parcelable would help you, as that would create distinct copies for the different Activities to use.
Shachar
You need to have that class implement Parcelable
It's basically kinda similar to Java's serializable. You have to tell your class how to pack and unpack itself. Then you can just put it in an intent via intent.putExtra();
Here is the code example taken from that link
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();
}
}

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