I have a class that contains data i want to pass it between intents, this class have arraylist that contains another class objects. this is my class
public class ParsedData implements Parcelable {
public String error;
public float protectionLevel;
public int protectionLevelColor;
public double lastBackup;
public boolean compressedType;
public Long driveFreeSpaceSize;
ArrayList<Item>Items = new ArrayList<Item>();
}
class Item {
public String name;
public float percentage;
public int files;
public long size;
}
how can i send this class between intents ?
you can let your class Item implements the Serializable interface, and use Intent.putExtra(String, Serializable). Since ArrayList implements also the Serializable interface, you can pass the whole Items object.
This may be your problem:
Classes implementing the Parcelable interface must also have a static field called CREATOR, which is an object implementing the Parcelable.Creator interface.
Alternatively, I'd try to have Item implement Parcelable, as well.
The fail-safe alternative is to write your data structure into a JSON string, which also allows you to pass the data to other applications that don't have access to your ParsedData class.
You may take a look at Intent.putExtra(String name, Parcelable object) and implement the parcelable interface in your class.
i have found the answer after all. thanks all how helped me
this is the answer:
import android.os.Parcel;
import android.os.Parcelable;
public class ParsedData implements Parcelable {
public String error;
public float protectionLevel;
public int protectionLevelColor;
public double lastBackup;
public boolean compressedType;
public Long statusSendTime;
ArrayList<Item>Items = new ArrayList<Item>();
//---------------------Constructors---------------------------
public ParsedData() { ; };
public ParsedData(Parcel in) {
readFromParcel(in);
}
//------------------------------------------------------------
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(error);
dest.writeFloat(protectionLevel);
dest.writeInt(protectionLevelColor);
dest.writeDouble(lastBackup);
dest.writeByte((byte) (compressedType ? 1 : 0));
dest.writeLong(statusSendTime);
dest.writeList(Items);
}
private void readFromParcel(Parcel in) {
error = in.readString();
protectionLevel = in.readFloat();
protectionLevelColor = in.readInt();
lastBackup = in.readDouble();
compressedType =in.readByte() == 1;
statusSendTime = in.readLong();
in.readList(Items,Item.class.getClassLoader() );
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public ParsedData createFromParcel(Parcel in) {
return new ParsedData(in);
}
public ParsedData[] newArray(int size) {
return new ParsedData[size];
}
};
}
class Item implements Parcelable {
public String name;
public float percentage;
//---------------------Constructors---------------------------
public Item() {
}
public Item(Parcel in) {
readFromParcel(in);
}
//------------------------------------------------------------
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeFloat(percentage);
}
public static final Creator<Item> CREATOR = new Creator<Item>() {
public Item createFromParcel(Parcel source) {
return new Item(source);
}
public Item[] newArray(int size) {
return new Item[size];
}
};
private void readFromParcel(Parcel in) {
this.name = in.readString();
this.percentage = in.readFloat();
}
}
and in the caller activity
ParsedData data = new PArsedData();
Intent intentBreakDown = new Intent(this,BreakDownBarActivity.class);
intentBreakDown.putExtra("data", data);
startActivity(intentBreakDown);
in the called activity(BreakDownBarActivity in my case)
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.breakdownbar);
Bundle b = getIntent().getExtras();
ParsedData data = (ParsedData)b.getParcelable("data");
}
Related
I have a Parcelable object that has a list of Parcelable objects. I am trying to read that list back after it has been passed from one Activity to the next, but only the first element is "un-bundled"
public class MyBundle implements Parcelable {
private List<Data> dataList;
public static final Parcelable.Creator<MyBundle> CREATOR = new Parcelable.Creator<MyBundle>() {
public MyBundle createFromParcel(Parcel in) {
return new MyBundle(in);
}
public MyBundle[] newArray(int size) {
return new MyBundle[size];
}
};
public MyBundle() {
}
public MyBundle(Parcel in) {
//dataList = new ArrayList<>();
//in.readTypedList(dataList, Data.CREATOR);
dataList = in.createTypedArrayList(Data.CREATOR);
//BOTH have the same result
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
if (dataList != null && dataList.size() > 0) {
dest.writeTypedList(dataList);
}
}
}
The data object:
/*BaseObject has the following properties:
UUID uuid;
long databaseId;
createdDate;
modifiedDate;
*/
public class Data extends BaseObject implements Parcelable {
private String name;
private String serial;
private String location;
public Data() {}
private Data(Parcel in) {
String uuidString = in.readString();
if (uuidString == null) return; //this is null!
uuid = UUID.fromString(idString);
databaseId = in.readLong();
createdDate = new Date(in.readLong());
modifiedDate = new Date(in.readLong());
location = in.readString();
name = in.readString();
serial = in.readString();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(uuid.toString());
dest.writeLong(databaseId);
dest.writeLong(createdDate.getTime());
dest.writeLong(modifiedDate.getTime());
dest.writeString(name);
dest.writeString(serial);
}
public static final Parcelable.Creator<Data> CREATOR
= new Parcelable.Creator<Data>() {
public Data createFromParcel(Parcel in) {
return new Data(in);
}
public Data[] newArray(int size) {
return new Data[size];
}
};
}
What I have tried:
Debugging - I can see the first element is read fine but the rest are return null, and they do have values when they are being written
"Android, How to use readTypedList method correctly in a Parcelable class?"
"how to properly implement Parcelable with an ArrayList?"
So this is the answer: My Data parcelable misses the location element when it creates the parcel. This obviously results in some kind of offset error when READING occurs. So the coded solution is as follows:
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(uuid.toString());
dest.writeLong(databaseId);
dest.writeLong(createdDate.getTime());
dest.writeLong(modifiedDate.getTime());
dest.writeString(location); /*HERE!*/
dest.writeString(name);
dest.writeString(serial);
}
I hope this helps someone else.
I have the following models:
GitItem:
public class GitItem implements Serializable, Parcelable {
public int id;
public String name;
public String full_name;
public GitOwner owner;
public GitItem() {
}
public GitItem(Parcel in) {
id = in.readInt();
name = in.readString();
full_name = in.readString();
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags){
out.writeInt(id);
out.writeString(name);
out.writeString(full_name);
}
public static final Parcelable.Creator<GitItem> CREATOR = new Parcelable.Creator<GitItem>(){
#Override
public GitItem createFromParcel(Parcel source) {
return new GitItem(source);
}
#Override
public GitItem[] newArray(int size) {
return new GitItem[size];
}
};
}
and GitOwner:
public class GitOwner implements Serializable, Parcelable {
public String avatar_url;
public GitOwner(Parcel in) {
avatar_url = in.readString();
}
public GitOwner() {
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
}
public static final Parcelable.Creator<GitOwner> CREATOR = new Parcelable.Creator<GitOwner>(){
#Override
public GitOwner createFromParcel(Parcel source) {
return new GitOwner(source);
}
#Override
public GitOwner[] newArray(int size) {
return new GitOwner[size];
}
};
}
and then in MainActivity.java I have a List<GitItem> data; which is bound to my RecyclerView.
Basically what I am trying to achieve, is to store current state of my List<GitItem> when I change Activity or simply rotate device. Unfortunately, even though I have implemented Parcelable (as suggested by other posts), I was unable to store the instance.
Any help in this matter would be highly appreciated.
You have not implemented the complete body of Parcelable functions i.e writeToParcel in GitOwner and GitItem class
In GitOwner class
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(avatar_url);
// add this line
}
and inside GitItem use writeParcelable to write and readParcelable to read GitItem object otherwise it won't be persisted and restored
public GitItem(Parcel in) {
id = in.readInt();
name = in.readString();
full_name = in.readString();
owner = in.readParcelable(GitItem.class.getClassLoader());
// Add line to read owner object
}
public void writeToParcel(Parcel out, int flags){
out.writeInt(id);
out.writeString(name);
out.writeString(full_name);
out.writeParcelable(owner , flags);
// Add line to write owner object
}
I've a custom parcelable (simplified) that contains a string array:
public class MyClass implements Parcelable {
public static final Creator<MyClass> CREATOR = new Creator<MyClass>() {
public MyClass createFromParcel(Parcel in) {
return new MyClass(in);
}
public MyClass[] newArray(int size) {
return new MyClass[size];
}
};
#SerializedName(“tips”)
private List<String> Tips;
public MyClass() {
Tips = new ArrayList<>();
}
protected Category(Parcel in) {
Tips = in.createStringArrayList();
}
public List<String> getTips() {
return Tips;
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeStringList(Tips);
}
}
I'm trying to pass this parcelable via Intent to another activity. The process is VERY slow and sometimes I get an OOM exception...I don't understand why, I just want to pass a string array...
Save your array into database and pass id of that record.
I have a class with the following structure:
class Example {
Integer age;
String name;
Collection<Example2>examples;
class Example2 {
Integer number;
Collection<String>strings;
}
}
How can I make this class implement Parcelable so that I can send its object across activities.
The simplest way will be to use #AutoParcel and let it handle the heavy lifting for you.
You should take a look at this thread : Android: Making a class parcelable
So your classes should be something like :
class Example implements Parcelable {
Integer age;
String name;
ArrayList<Example2> examples;
public Example(Parcel in) {
examples = new ArrayList<>();
readFromParcel(in);
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(age);
dest.writeString(name);
dest.writeList(examples != null ? examples : new ArrayList());
}
private void readFromParcel(Parcel in) {
age = in.readInt();
name = in.readString();
in.readList(examples, Example2.class.getClassLoader());
}
public static final Creator<Example> CREATOR = new Creator<Example>() {
#Override
public Example createFromParcel(Parcel in) {
return new Example(in);
}
#Override
public Example[] newArray(int size) {
return new Example[size];
}
};
}
and
class Example2 implements Parcelable {
Integer number;
ArrayList<String> labels;
public Example2(Parcel in) {
labels = new ArrayList<>();
readFromParcel(in);
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInteger(number);
dest.writeList(labels != null ? labels : new ArrayList());
}
#Override
public int describeContents() {
return 0;
}
private void readFromParcel(Parcel in) {
number = in.readInteger();
in.readStringList(labels);
}
public static final Creator<Example2> CREATOR = new Creator<Example2>() {
#Override
public Example2 createFromParcel(Parcel in) {
return new Example2(in);
}
#Override
public Example2[] newArray(int size) {
return new Example2[size];
}
};
}
First of all i have check this answer.
What i am trying to do is extending Location class calling it LocationPlus which has some
member variables. functionality i am trying to achieve is pass the object of LocationPlus class from one activity to another.
Here is my CREATOR
public static final Parcelable.Creator<LocationPlus> CREATOR = new Parcelable.Creator<LocationPlus>() {
#Override
public LocationPlus createFromParcel(Parcel source) {
return new LocationPlus(source);
}
#Override
public LocationPlus[] newArray(int size) {
return new LocationPlus[size];
}
};
problem i am facing is this error
Implicit super constructor Location() is undefined. Must explicitly invoke another constructor
when trying to write constructor
public LocationPlus(Parcel in) {
Someone in comment ask me to post LocationPlus class so here it is
public class LocationPlus extends Location{
private int mBattery = -1;
public LocationPlus(String locationName) {
super(locationName);
}
public LocationPlus(Location location) {
super(location);
}
public int getmBattery() {
return mBattery;
}
public void setmBattery(int mBattery) {
this.mBattery = mBattery;
}
#Override
public int describeContents() {
return 0;
}
public static final Parcelable.Creator<LocationPlus> CREATOR = new Parcelable.Creator<LocationPlus>() {
#Override
public LocationPlus createFromParcel(Parcel source) {
return new LocationPlus(source);
}
#Override
public LocationPlus[] newArray(int size) {
return new LocationPlus[size];
}
};
#Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(mBattery);
}
public LocationPlus(Parcel in) {
mBattery =in.readInt();
}
}
Parcelable, the Speed King
According to google engineers, this code will run significantly faster. One of the reasons for this is that we are being explicit about the serialization process instead of using reflection to infer it. It also stands to reason that the code has been heavily optimized for this purpose.
public abstract class BaseClass implements Parcelable {
public String FullName;
public boolean IsValidUser;
public String UserName;
public BaseClass () {
}
protected BaseClass(Parcel in) {
FullName = in.readString();
IsValidUser = in.readByte() != 0;
UserName = in.readString();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(FullName);
dest.writeByte((byte) (IsValidUser ? 1 : 0));
dest.writeString(UserName);
}
}
Child class will be as follows with usage of list adding into parcelable object:
public class DerivedClass extends BaseClass {
public boolean IsSuccess;
public String Message;
public List<AnotherClass> AnotherClassObj;
public DerivedClass () {
super();
}
protected DerivedClass(Parcel in) {
super(in);
AnotherClassObj = new ArrayList<AnotherClass>();
IsSuccess = in.readByte() != 0;
Message = in.readString();
AnotherClassObj = in.readArrayList(AnotherClass.class.getClassLoader());
}
public static final Creator<DerivedClass> CREATOR = new Creator<DerivedClass>() {
#Override
public DerivedClass createFromParcel(Parcel in) {
return new DerivedClass(in);
}
#Override
public DerivedClass[] newArray(int size) {
return new DerivedClass[size];
}
};
#Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeByte((byte) (IsSuccess ? 1 : 0));
dest.writeString(Message);
dest.writeList(AnotherClassObj);
}
public int describeContents() {
return 0;
}
}
Another child class :
public class AnotherClass extends BaseClass {
public AnotherClass() {
super();
}
protected AnotherClass(Parcel in) {
super(in);
}
public int describeContents() {
return 0;
}
public static final Creator<AnotherClass> CREATOR = new Creator<AnotherClass>() {
#Override
public AnotherClass createFromParcel(Parcel in) {
return new AnotherClass(in);
}
#Override
public AnotherClass[] newArray(int size) {
return new AnotherClass[size];
}
};
#Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
}
}
In Activity:
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.putExtra("UserObject", parcelableObject);
startActivity(intent);
finish();
In receiving activity:
Bundle extras = getIntent().getExtras();
if (extras != null) {
userObject = extras.getParcelable("UserObject");
}
Hi I've do research a lot about this, but I couldn't find useful anything. I try solution below and it worked for me.
Let say your super class has only int variable named "mData".
public class Location implements Parcelable {
protected int mData;
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mData);
}
public static final Parcelable.Creator<Location> CREATOR
= new Parcelable.Creator<Location>() {
public Location createFromParcel(Parcel in) {
return new Location(in);
}
public Location[] newArray(int size) {
return new Location[size];
}
};
private Location(Parcel in) {
mData = in.readInt();
}
}
Then, your extended class has only int variable named "mBattery".
public class LocationPlus extends Location {
protected int mBattery;
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mBattery);
}
public static final Parcelable.Creator<LocationPlus> CREATOR
= new Parcelable.Creator<LocationPlus>() {
public LocationPlus createFromParcel(Parcel in) {
return new LocationPlus(in);
}
public LocationPlus[] newArray(int size) {
return new LocationPlus[size];
}
};
private LocationPlus(Parcel in) {
mBattery = in.readInt();
}
}
So far, LocationPlus works fine. But we don't set variable of super class. Firstly, I set super class' variables on extended class with super(..) method. But it didn't work.
private LocationPlus(Parcel in) {
super(in);
mBattery = in.readInt();
}
Instead of code above, you should set all super class' variables explicitly. Super class' variables should be protected. Final constructor should be like this:
private LocationPlus(Parcel in) {
mData = in.readIn();
mBattery = in.readInt();
}
and writeToParcel method should be like this:
public void writeToParcel(Parcel out, int flags) {
out.writeIn(mData);
out.writeInt(mBattery);
}
Try this solution:
public static final Parcelable.Creator<LocationPlus> CREATOR =
new Parcelable.Creator<LocationPlus>() {
#Override
public LocationPlus createFromParcel(Parcel in) {
Location l = Location.CREATOR.createFromParcel(in);
LocationPlus lp = new LocationPlus(l);
lp.mBattery= in.readInt();
return lp;
}
#Override
public LocationPlus[] newArray(int size) {
return new LocationPlus[size];
}
};
#Override
public void writeToParcel(Parcel parcel, int flags) {
super.writeToParcel(parcel, flags);
parcel.writeInt(mBattery);
}
According to the Android docs, there isn't a Location() constructor for the Location class. When initializing your LocationPlus class, you need to call either super(String provider) or super(Location l).
Edit: Corrected syntax
(See Location Android Doc)