Serializable SparseArray<Custom Object> - android

I want to send my data from Activity1 to Activity2 with putExtra.
My Custom object implements Serializable :
public class ARObjectCategory implements Serializable {
private static final long serialVersionUID = 3128594851129501738L;
public int id;
public String name;
public transient ARObjectCategory parent;
public transient SparseArray<ARObjectCategory> children;
public transient Bitmap iconBitmap = null;
public String icon;
private boolean active = false;
public ARObjectCategory(int id, String name, ARObjectCategory parent) {
this.id = id;
this.name = name;
this.parent = parent;
this.children = new SparseArray<>();
}
public void addChild(ARObjectCategory child) {
children.append(child.id, child);
if (getActive())
child.setActive(true);
}
public final ARObjectCategory getChild(int index) {
return children.valueAt(index);
}
public final SparseArray<ARObjectCategory> getChildren() {
return this.children;
}
public final int getParentLast() {
ARObjectCategory parentTemp = this.parent;
while (parentTemp.parent != null) {
parentTemp = parentTemp.parent;
}
return parentTemp.id;
}
public final ARObjectCategory getChildById(int id) {
return children.get(id, null);
}
public final int getChildrenCount() {
return children.size();
}
public Boolean getActive() {
return this.active;
}
public void setActive(Boolean bool) {
this.active = bool;
}
public Bitmap getIconBitmap() {
return iconBitmap;
}
public void setIconBitmap(Bitmap iconBitmap) {
this.iconBitmap = iconBitmap;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
}
Activity1.java (Sender):
ARObjectCategory test1= adapter.getItem(position);
Intent subCat= new Intent(getActivity(), SubCategoriesActivity.class);
subCat.putExtra("test",test1);
subCat.putExtra("selected",position);
startActivity(subCat);
On Debug Mode my object looks ok. SpraseArray got object of AROjcectCategory.
Activity2.java (Reciever):
Bundle extras = getIntent().getExtras();
if (extras != null) {
int selected = extras.getInt("selected", -1);
ARObjectCategory list = (ARObjectCategory) extras.getSerializable("test");
SparseArray<ARObjectCategory> lista = list.getChildren();
}
But when i debug the Activity2. I see that my SpraseArray of children is null
Finally when i remove the transient from my objects.
public transient ARObjectCategory parent;
public transient SparseArray<ARObjectCategory> children;
I am getting the following error on my logcat :
java.lang.RuntimeException: Parcelable encountered IOException
writing serializable object (name =
com.ethos.ar.core.ARObjectCategory) ........
Caused by:
java.io.NotSerializableException: android.util.SparseArray ......
What is the correct way to send Object that has SpraseArray to other Activity.
Tip: Parcelable is not working:
dest.writeParcelable(this.children);
SparseArray<ARObjectCategory> cannot be converted to SparseArray<Object>
Thanks

When you use the transient modifier, that member is excluded from the serialization process. That's the reason you are getting a null object. When you remove the transient modifier then you receive an exception, but why? That's because the "SparseArray" object itself doesn't implement the "Serializable" interface. Remember that in order to an object be serializable then all of its attributes must implement the "Serializable" interface. Now what can you do? You should implement the "Parcelable" interface of Android, but how? If you have problems using the "SparseArray" in the parcelable process then you can parcel it to another object and the recreate the original "SparseArray" object in the creation process.

Related

Null bundle when passing from activity to fragment

When trying to pass a custom object from an activity to a fragment by using a bundle, I kept getting a null bundle when I tried to retrieve it in the fragment. I am using parcels since they are the only option for custom arraylists. Any help appreciated!
To show that my class is parcelable:
public class Exercise implements Parcelable{
private String mName;
private String mMuscleGroup;
private String mType;
private String mEquipment;
private float mWeight;
private int mReps;
private int mSet;
public Exercise(String name, String MuscleGroup, String type, String equipment, float weight, int reps, int set) {
mName = name;
mMuscleGroup = MuscleGroup;
mType = type;
mEquipment = equipment;
mWeight = weight;
mReps = reps;
mSet = set;
}
private Exercise(Parcel in) {
mName = in.readString();
mMuscleGroup = in.readString();
mType = in.readString();
mEquipment = in.readString();
mWeight = in.readFloat();
mReps = in.readInt();
mSet = in.readInt();
}
public static final Creator<Exercise> CREATOR = new Creator<Exercise>() {
#Override
public Exercise createFromParcel(Parcel in) {
return new Exercise(in);
}
#Override
public Exercise[] newArray(int size) {
return new Exercise[size];
}
};
public String getName() {
return mName;
}
public String getMuscleGroup() {
return mMuscleGroup;
}
public String getType() {
return mType;
}
public String getEquipment() {
return mEquipment;
}
public float getWeight() { return mWeight; }
public int getReps() { return mReps; }
public int getSet() { return mSet; }
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(mName);
parcel.writeString(mMuscleGroup);
parcel.writeString(mType);
parcel.writeString(mEquipment);
parcel.writeFloat(mWeight);
parcel.writeInt(mReps);
parcel.writeInt(mSet);
}
}
'''
Activity I am passing bundle from:
#Override
protected void onPause() {
// send ArrayList of exercises to WorkoutsFragment
WorkoutsFragment workoutsFragment = new WorkoutsFragment();
Bundle bundle = new Bundle();
bundle.putSerializable("exercise", exercise);
workoutsFragment.setArguments(bundle);
// clear exercise ArrayList
super.onPause();
}
Fragment receiving bundle:
Bundle bundle = this.getArguments();
if(bundle != null) {
exercise = bundle.getParcelableArrayList("exercise");
}
You need to use bundle.putParcelableArrayList to put Parcelable list objects, not putSerializable
If the types don't match, you get null

Creating and passing object to activity fails

I want to create and pass an object through intent to another activity, so I can process the object details in this activity and show it to the user.
This object is being identified by a value long.
I have an arraylist (releaseIds) which holds several long values of this object, so I just want to pass these values through an intent to the other activity.
The user can select the desired object from a alertdialog presenting this list, once he/she selects an item from this list the correct long ID is identified and a new object created and passed through intent.
But creating the new object somehow failes, because the object ReleaseModel is null in the receiving acitivity.
What I am doing wrong?
Creating and passing the object (ReleaseModel):
...
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
// Do something with the selection
for (int i = 0; i < releaseIds.size(); i++) {
if (i == item) {
long ID = releaseIds.get(i);
final ReleaseModel releaseModel = new ReleaseModel(ID);
ReleaseActivtiy_.intent(MyAppsMain.this).extra("releaseModel",
releaseModel).start();
}
}
}
});
...
The object itself:
public class ReleaseModel extends BaseModel {
private List<String> url = new ArrayList<>();
private boolean liked;
...
public ReleaseModel() {
}
public ReleaseModel(long id) {
super(id);
}
...
public void writeToParcel(Parcel parcel, int flags) {
super.writeToParcel(parcel, flags);
parcel.writeInt(liked ? 1 : 0);
...
}
public static final Parcelable.Creator<ReleaseModel> CREATOR = new Parcelable.Creator<ReleaseModel>() {
public ReleaseModel createFromParcel(Parcel in) {
return new ReleaseModel(in);
}
public ReleaseModel[] newArray(int size) {
return new ReleaseModel[size];
}
};
private ReleaseModel(Parcel parcel) {
super(parcel);
setLiked(parcel.readInt() == 1);
...
}
}
The basemodel:
public class BaseModel implements Parcelable {
private long id;
private long date;
...
public BaseModel() {
}
public BaseModel(long id) {
this.id = id;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
...
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeLong(id);
parcel.writeLong(date);
...
}
public static final Parcelable.Creator<BaseModel> CREATOR = new Parcelable.Creator<BaseModel>() {
public BaseModel createFromParcel(Parcel in) {
return new BaseModel(in);
}
public BaseModel[] newArray(int size) {
return new BaseModel[size];
}
};
public BaseModel(Parcel parcel) {
setId(parcel.readLong());
setDate(parcel.readLong());
...
}
}
Receiving activity:
#EActivity(R.layout.release_activity)
public class ReleaseActivtiy extends BaseActivity implements LoaderManager
.LoaderCallbacks<BaseResponse>, NotificationCenter.NotificationCenterDelegate {
...
#Extra("releaseModel")
ReleaseModel releaseModel;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
}
#AfterViews
public void init() {
// Nullpointer exception on this line for releaseModel
String temp = releaseModel.getSubject().replaceAll("[^a-zA-Z]", "");
}
}
To pass ReleaseModel object to another Activity(ActivityPassedTo).
Do the Following Steps:
1.You Need to make ReleaseModel implements Serializable
2.To pass it to an Intent you need to have a Unique Key to identify the object passed in both the activities
Eg. you can create a Key:
static final String RELEASE_MODEL = "RELEASE_MODEL";
Now pass it to the activity in intent
Intent intent = new Intent(this,ActivityPassedTo.class);
intent.putExtra(RELEASE_MODEL,releaseModelObject);
startActivity(intent);
Now Retrieve the object in Activity (ActivityPassedTo)
Intent intent = getIntent()
ReleaseModel releaseModel = (ReleaseModel)intent.getSerializableExtra(RELEASE_MODEL);

Singleton constructor crashes my app

I'm testing out the model layer of my application and I want to add an element to a list. But whenever I try to add some data into my data model the application crashes. I cannot find the reason for this.
My code for the data model.
public class DataModel {
private List<Log> logs;
private static DataModel instance;
private Context ctx;
//Singleton constructor
private DataModel()
{
//This makes it crash
logs.add(new Log("1234","sms", 123545, 1, 0));
//Load logs from database - Not done yet.
}
public static DataModel getInstance()
{
if (instance == null)
{
//Creates the instance
instance = new DataModel();
}
return instance;
}
My code for log
public class Log {
private String phonenumber;
private String type;
private long date;
private int incoming;
private int outgoing;
private long id;
//Constructor for incoming sms or call
public Log( String Phonenumber, String Type, long Date, int Incoming, int Outgoing)
{
this.phonenumber = Phonenumber;
this.type = Type;
this.date = Date;
this.incoming = Incoming;
this.outgoing = Outgoing;
}
public long getId()
{
return id;
}
public void setId(long id)
{
this.id = id;
}
public String getPhonenumber()
{
return phonenumber;
}
public void setPhonenumer(String phonenumber)
{
this.phonenumber = phonenumber;
}
public String getType()
{
return type;
}
public void setType(String type)
{
this.type = type;
}
public long getDate()
{
return date;
}
public void setDate(long date)
{
this.date = date;
}
public int getIncoming()
{
return incoming;
}
public void setIncoming(int incoming)
{
this.incoming = incoming;
}
public int getOutgoing()
{
return outgoing;
}
public void setOutgoing (int outgoing)
{
this.outgoing = outgoing;
}
You are not initializing logs. Its null when you execute this statement:
logs.add(new Log("1234","sms", 123545, 1, 0));
Change:
private List<Log> logs;
to:
private List<Log> logs = new ArrayList<Log>();
I see a context in your code, but you don't set it or use it anywhere so maybe you stripped part of your code. In relation to that, if you use it to UI related stuff (and some other cases) I can guarantee you that it will crash your app if you don't reset it every time the screen orientation changes or you change activities.
You have not Instantiated list object
private List<Log> logs;
Update your constructor to this
//Singleton constructor
private DataModel()
{
//This makes it crash
logs = new ArrayList<Log>();
logs.add(new Log("1234","sms", 123545, 1, 0));
//Load logs from database - Not done yet.
}
Now every time you constructor gets called you will get a fresh copy of list object.
Initialize the List before use
you can initialize the List in Constructor as well
public class DataModel {
private List<Log> logs= new ArrayList<Log>();
private static DataModel instance;
private Context ctx;
//Singleton constructor
private DataModel()
{
//This makes it crash
logs.add(new Log("1234","sms", 123545, 1, 0));
int i=0;
//Load logs from database - Not done yet.
}
public static DataModel getInstance()
{
if (instance == null)
{
//Creates the instance
instance = new DataModel();
}
return instance;
}
}
Don't initialize globally logs and also use synchronized getInstance method so that only one instance should get created if two threads are trying to access at the same time.
Use this code:
public class DataModel {
private List<Log> logs;
private static DataModel instance;
private Context ctx;
//Singleton constructor
private DataModel()
{
if(logs == null){
logs = new ArrayList<Log>();
}
logs.add(new Log("1234","sms", 123545, 1, 0));
//Load logs from database - Not done yet.
}
public synchronized static DataModel getInstance()
{
if (instance == null)
{
//Creates the instance
instance = new DataModel();
}
return instance;
}

Passing Parcelable item between activities

I'm having trouble passing an object via an Intent. I keep getting a null pointer error. here it is:
In my ListActivity:
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = new Intent(MyListActivity.this, DetailsActivity.class);
intent.putExtra("this_item", my_array.get(position));
startActivity(intent);
}
In the onCreate() of the DetailsActivity class:
thisItem = (MyObject) getIntent().getExtras().getParcelable("this_item");
System.err.println(thisItem.getDescription()); //<--Null pointer error!
The MyObject class does implement Parcelable. Why can't I pass this object over? I'm confused. Thanks for any help.
EDIT: Here is that class:
public class MyObject implements Comparable<MyObject>, Parcelable {
private Date date;
private MyType my_type;
private String description;
private int flags;
public MyObject(Date date, MyType type, String desc) {
this.date = date;
this.my_type = type;
this.description = desc;
}
public Date getDate() {return date;}
public MyType getMyType() {return my_type;}
public String getDescription() {return description;}
public int compareTo(MyObject another) {
if (getDate() == null || another.getDate() == null) {return 0;}
return getDate().compareTo(another.getDate());
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(flags);
}
public static final Parcelable.Creator<MyObject> CREATOR = new Parcelable.Creator<MyObject>() {
public MyObject createFromParcel(Parcel in) {
return new MyObject(in);
}
public MyObject[] newArray(int size) {
return new MyObject[size];
}
};
private MyObject (Parcel in) {
flags = in.readInt();
}
}
If you want to pass the data from one activity to another actiivty via intent the object must be parcelable or serializable in android..for parcelable you have to implement the serializable interface..for parcelable you must implement parcelable interface..
Write parcelable class like this..
parcel example

Passing complex data directly between Fragments?What's wrong with the code?

i want to pass data between 2 fragments.the data i am passing is an object of a class SongDetails.Here is the Code for the fragment which is passing the data
ArrayList<SongDetails> Songinfo =new........;
if (Songinfo.size()>0)//Songinfo is an object of the class SongDetails..
{
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("Fragdata",Songinfo);
dv.setArguments(bundle);
}
code for receiving the data
Bundle bundle=this.getArguments();
final ArrayList<SongDetails> Songinfo =bundle.getParcelableArrayList("Fragdata");
when i run this it the app crashes...what am i be doing wrong??
the code for the SongDetails
package sourcecode.jazzplayer;
import android.graphics.Bitmap;
import android.os.Parcel;
import android.os.Parcelable;
public class SongDetails implements Parcelable {
Bitmap icon;
String song;
String Artist;
String Album;
String Path;
int time;
int icLauncher;
public SongDetails() {
}
public SongDetails(Parcel in) {
String[] data = new String[4];
in.readStringArray(data);
this.Path = data[0];
this.song= data[1];
this.Album= data[2];
this.Artist = data[3];
}
public String getSong() {
return song;
}
public void setSong(String song) {
this.song = song;
}
public String getArtist() {
return Artist;
}
public void setArtist(String Artist) {
this.Artist = Artist;
}
public Bitmap getIcon() {
return icon;
}
public void setIcon(Bitmap bitmap) {
this.icon = bitmap;
}
public String getPath2() {
return Path;
}
public void setPath2(String Path) {
this.Path = Path;
}
public String getAlbum() {
return Album;
}
public void setAlbum(String Album) {
this.Album = Album;
}
public void setIcon(int icLauncher) {
this.icLauncher = icLauncher;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeStringArray(new String[] { this.Path,this.song,this.Album,this.Artist });
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public SongDetails createFromParcel(Parcel in) {
return new SongDetails(in);
}
public SongDetails[] newArray(int size) {
return new SongDetails[size];
}
};
}
You can't pass data directly between 2 fragments. Instead you have to pass data from your fragment 1 to your activity through an interface that you must have previously created.
Then, inside the implemented method in your activity, you should retrieve the object reference to fragment 2 and call a public method that you created and do the job.
There is a good tutorial in Android official documentation:
Android Fragments
To path any data from anywhere to anywhere else in your app use EventBus library. You can also do it by implementing observer design pattern but using library is far more easier since it also handles thread switching for you (just in case you need it)
here is the link
https://github.com/greenrobot/EventBus

Categories

Resources