The last of the getParcelableArrayList element appears as empty string - android

When I put the parcelable arraylist in the bundle and get it with getParcelableArrayList, all elements are showing correctly, while the last element is showing as empty string.
My custom Parcelable item:
public class Media implements Parcelable {
private final Uri uri;
private Type type;
private InfoModel infoModel;
public Media(Uri uri, Type type) {
this.uri = uri;
this.type = type;
this.infoModel = InfoModel.empty();
}
public Media() {
this.uri = null;
this.type = Type.image;
this.infoModel = InfoModel.empty();
}
protected Media(Parcel in) {
uri = in.readParcelable(Uri.class.getClassLoader());
type = Type.valueOf(in.readString());
infoModel = in.readParcelable(InfoModel.class.getClassLoader());
}
public void setInfoModel(InfoModel infoModel) {
this.infoModel = infoModel;
}
public InfoModel getInfoModel() {
return infoModel;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(uri, flags);
dest.writeString(this.type.name());
dest.writeParcelable(infoModel, flags);
}
public static final Creator<Media> CREATOR = new Creator<Media>() {
#Override
public Media createFromParcel(Parcel in) {
return new Media(in);
}
#Override
public Media[] newArray(int size) {
return new Media[size];
}
};
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Media media = (Media) o;
return uri.equals(media.uri);
}
#Override
public int hashCode() {
return uri.hashCode();
}
}
When I check the media list in bundle, I see there is no problem -> bundleIntent function:
public class ShowMediaActivity extends Activity {
public static Intent buildIntent(#NonNull ArrayList<Media> medias) {
Intent intent = new Intent(this, ShowMediaActivity.class);
Bundle b = new Bundle();
b.putParcelableArrayList(KEY_MEDIA, medias);
intent.putExtra("bundle", b);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return intent;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
Logger.i();
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_container);
Bundle b = getIntent().getBundleExtra("bundle");
List<Media> initialMedia = new ArrayList<>();
if (b != null) {
initialMedia = b.getParcelableArrayList(KEY_MEDIA);
}
}
initialMedia elements in onCreate:
initialMedia has 1 elements : Media
initialMedia has 2 elements : Media, ""
initialMedia has 3 elements : Media, Media, ""
initialMedia has 4 elements : Media, Media, Media, ""

I left an item that I converted to long in InfoModel class in in.readInt() instead of in.readLong(). I was not aware of it at all. Thank you for your help #emandt
public InfoModel(Parcel in) {
startTime = in.readLong();
endTime = in.readLong();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(startTime);
dest.writeLong(endTime);
}

Related

How to display data from one activity's recyclerView to another activity's recyclerView using parcelable

I have been trying to display model Arraylist from one activity (data displayed in recyclerview) to another activity's recyclerView by using parcelable.
I have managed to implement the parcelable part. I want to know, how to display it in the recyclerView for second activity.
FirstActivity.java
//Adding data to 1st activitiy's recyclerview
ArrayList<PersModel> persModels = new ArrayList<PersModel>();
private void addPers(int perID, String perRole, int perCS, int perCC) {
PersModel PersDataModel = new PersModel();
PersDataModel.setPerId(perID);
PersDataModel.setPerCat(perRole);
PersDataModel.setPerCleanStatus(perCS);
PersDataModel.setPerCleanCode(perCC);
persModels.add(PersDataModel);
recyclerViewAdapter.updateModels(persModels);
}
//Starting next activity
btnReview.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(AddPersonActivity.this, ReviewActivity.class);
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("mylist", persModels);
intent.putExtras(bundle);
startActivity(intent);
}
});
SecondActivity.java
//Data passed from FirstActivity.java
Bundle bundle = getIntent().getExtras();
ArrayList<PersModel> arraylist = bundle.getParcelableArrayList("mylist");
//Add data to new model..THIS IS WRONG
private void displayPersList( ArrayList arrayList){
List<PersDisplayModel> newModels = new ArrayList<>();
for (int i = 0; i < arrayList.size(); i++) {
PersDisplayModel GetJobsDataModel = new PersDisplayModel();
try {
GetJobsDataModel.setPerId(arrayList.get());
GetJobsDataModel.setPerCat(perRole);
GetJobsDataModel.setPerCleanStatus(perCS);
GetJobsDataModel.setPerCleanCode(perCC);
newModels.add(GetJobsDataModel);
} catch (JSONException e) {
e.printStackTrace();
}
}
if (array.length() != 0) {
recyclerViewAdapter.updateModels(newModels);
}
}
PersModel.java
public class PersModel implements Parcelable {
int perId;
int perCleanStatus;
int perCleanCode;
String perCat;
public PersModel() {
}
public int getPerId() {
return perId;
}
public void setPerId(int perId) {
this.perId = perId;
}
public int getPerCleanStatus() {
return perCleanStatus;
}
public void setPerCleanStatus(int perCleanStatus) {
this.perCleanStatus = perCleanStatus;
}
public int getPerCleanCode() {
return perCleanCode;
}
public void setPerCleanCode(int perCleanCode) {
this.perCleanCode = perCleanCode;
}
public String getPerCat() {
return perCat;
}
public void setPerCat(String perCat) {
this.perCat = perCat;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(perId);
dest.writeInt(perCleanStatus);
dest.writeInt(perCleanCode);
dest.writeString(perCat);
}
public PersModel(Parcel in) {
perId = in.readInt();
perCleanStatus = in.readInt();
perCleanCode = in.readInt();
perCat = in.readString();
}
public static final Creator<PersModel> CREATOR = new Creator<PersModel>() {
#Override
public PersModel createFromParcel(Parcel in) {
return new PersModel(in);
}
#Override
public PersModel[] newArray(int size) {
return new PersModel[size];
}
};
}
I am going to assume that PersModel and PersDisplayModel have the same setters and getters.
You need to change this:
GetJobsDataModel.setPerId(arrayList.get(i));
GetJobsDataModel.setPerCat(perRole);
GetJobsDataModel.setPerCleanStatus(perCS);
GetJobsDataModel.setPerCleanCode(perCC);
To this:
GetJobsDataModel.setPerId(arrayList.get(i).getPerId());
GetJobsDataModel.setPerCat(arrayList.get(i).getPerCat());
GetJobsDataModel.setPerCleanStatus(arrayList.get(i).getPerCleanStatus());
GetJobsDataModel.setPerCleanCode(arrayList.get(i).getPerCleanCode());

In fragment, restore an object that contains a list of another object with Parcelable implementation

I have a Car class implements Parcelable:
public class Car implements Parcelable {
private long id;
private String model;
public Car(long id, String model) {
this.id = id;
this.model = model;
}
public String getModel() {
return model;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(this.id);
dest.writeString(this.model);
}
private Car(Parcel in) {
this.id = in.readLong();
this.model = in.readString();
}
public static final Creator<Car> CREATOR = new Creator<Car>() {
#Override
public Car createFromParcel(Parcel source) {
return new Car(source);
}
#Override
public Car[] newArray(int size) {
return new Car[size];
}
};
}
Then, I have a Store class which holds a list of cars, it also implements Parcelable:
public class Store implements Parcelable {
private List<Car> carList = new ArrayList<>();
public List<Car> getCarList() {
return carList;
}
public void setCarList(List<Car> cars) {
carList = cars;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedList(this.carList);
}
private Store(Parcel in) {
in.readTypedList(carList, Car.CREATOR);
}
public static final Creator<Store> CREATOR = new Creator<Store>() {
#Override
public Store createFromParcel(Parcel source) {
return new Store(source);
}
#Override
public Store[] newArray(int size) {
return new Store[size];
}
};
}
In a Fragment, I try to restore the Store instance named myStore, including the list of cars in it:
class MyFragment extends Fragment {
private Store myStore;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null && savedInstanceState.containsKey(MY_STORE)) {
myStore = savedInstanceState.getParcelable(MY_STORE);
// PROBLEM IS HERE:
// when runtime hit here, the restored myStore contains one car but has id with weird long value and null in model field. WHY?
} else {
// initialize myStore with car list (only one car)
Car myCar = new Car(1, "BMW X1");
List<Car> cars = new ArrayList<>();
cars.add(myCar);
myStore = new Store();
myStore.setCarList(cars);
}
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
if(myStore != null) {
outState.putParcelable(MY_STORE, myStore);
}
super.onSaveInstanceState(outState);
}
}
Problem occur when in MyFragment, code tries to restore myStore in onCreate(). At runtime , the restored myStore does contain one car in a list, but the car in that list has id with weird long value (e.g. 28429333427126393) and null in model field. WHY? What did I do wrong? How to restore an object contains a list of another object?
This problem usually occurs when your carList instance was null so you wrote a null object in parcelable and try to read from it.
One of the options is that you initialize your list when it's null and then write it in parcelable. Using this case your list will always have a reference after restoration which might not be what you're looking for.
The other approach is to write a byte value before writing your list into parcelable indicating that your list was null or you should expect some value from it. For this case I'm using this helper class which solved my own problem. Based on my needs, I have made some improvements. Here is my version if you'd prefer to use it:
public class ParcelableUtils {
public static void write(Parcel dest, String string) {
dest.writeByte((byte) (string == null ? 0 : 1));
if (string != null) {
dest.writeString(string);
}
}
public static String readString(Parcel source) {
if (source.readByte() == 1) {
return source.readString();
}
return null;
}
public static void write(Parcel dest, Parcelable parcelable, int flags) {
dest.writeByte((byte) (parcelable == null ? 0 : 1));
if (parcelable != null) {
dest.writeParcelable(parcelable, flags);
}
}
public static <T extends Parcelable> T readParcelable(Parcel source) {
if (source.readByte() == 1) {
return source.readParcelable(null);
}
return null;
}
public static <T extends Parcelable> T readParcelable(Parcel source, Class objectClass) {
if (source.readByte() == 1) {
return source.readParcelable(objectClass.getClassLoader());
}
return null;
}
public static void write(Parcel dest, Map<String, String> strings) {
if (strings == null) {
dest.writeInt(-1);
}
{
dest.writeInt(strings.keySet().size());
for (String key : strings.keySet()) {
dest.writeString(key);
dest.writeString(strings.get(key));
}
}
}
public static Map<String, String> readStringMap(Parcel source) {
int numKeys = source.readInt();
if (numKeys == -1) {
return null;
}
HashMap<String, String> map = new HashMap<String, String>();
for (int i = 0; i < numKeys; i++) {
String key = source.readString();
String value = source.readString();
map.put(key, value);
}
return map;
}
public static <T extends Parcelable> void write(Parcel dest, Map<String, T> objects, int flags) {
if (objects == null) {
dest.writeInt(-1);
} else {
dest.writeInt(objects.keySet().size());
for (String key : objects.keySet()) {
dest.writeString(key);
dest.writeParcelable(objects.get(key), flags);
}
}
}
public static <T extends Parcelable> Map<String, T> readParcelableMap(Parcel source) {
int numKeys = source.readInt();
if (numKeys == -1) {
return null;
}
HashMap<String, T> map = new HashMap<String, T>();
for (int i = 0; i < numKeys; i++) {
String key = source.readString();
T value = source.readParcelable(null);
map.put(key, value);
}
return map;
}
public static void write(Parcel dest, URL url) {
dest.writeString(url.toExternalForm());
}
public static URL readURL(Parcel source) {
try {
return new URL(source.readString());
} catch (MalformedURLException e) {
e.printStackTrace();
}
return null;
}
public static void write(Parcel dest, Date date) {
dest.writeByte((byte) (date == null ? 0 : 1));
if (date != null) {
dest.writeLong(date.getTime());
}
}
public static Date readDate(Parcel source) {
if (source.readByte() == 1) {
return new Date(source.readLong());
}
return null;
}
public static <T extends java.lang.Enum<T>> void write(Parcel dest, java.lang.Enum<T> enu) {
if (enu == null) {
dest.writeString("");
} else {
dest.writeString(enu.name());
}
}
public static <T extends java.lang.Enum<T>> T readEnum(Parcel dest, Class<T> clazz) {
String name = dest.readString();
if ("".equals(name)) {
return null;
}
return java.lang.Enum.valueOf(clazz, name);
}
public static void write(Parcel dest, boolean bool) {
dest.writeByte((byte) (bool ? 1 : 0));
}
public static boolean readBoolean(Parcel source) {
return source.readByte() == 1;
}
public static <T extends Parcelable> void write(Parcel dest,
List<T> fields, int flags) {
if (fields == null) {
dest.writeInt(-1);
} else {
dest.writeInt(fields.size());
for (T field : fields) {
dest.writeParcelable(field, flags);
}
}
}
#SuppressWarnings("unchecked")
public static <T extends Parcelable> List<T> readParcelableList(
Parcel source) {
int size = source.readInt();
if (size == -1) {
return null;
}
ArrayList<T> list = new ArrayList<T>();
for (int i = 0; i < size; i++) {
list.add((T) source.readParcelable(null));
}
return list;
}
}
Hope it helps.

Android Parcelable class for savedInstanceState

in my application i'm trying to use Parcelable class to save savedInstanceState bundle, for this action i'm create this below code:
public class SaveInstanceState implements Parcelable {
String stringStates;
Integer integerStates;
boolean booleanStates;
public SaveInstanceState(String str) {
this.stringStates = str;
}
public SaveInstanceState(Integer value) {
this.integerStates = value;
}
public SaveInstanceState(boolean value) {
this.booleanStates = value;
}
public SaveInstanceState(String str, Integer ivalue, boolean bvalue) {
this.stringStates = str;
this.integerStates = ivalue;
this.booleanStates = bvalue;
}
private SaveInstanceState(Parcel in) {
stringStates = in.readString();
integerStates = in.readInt();
booleanStates = in.readByte() != 0;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel out, int flags) {
out.writeString(stringStates);
out.writeInt(integerStates);
out.writeByte((byte) (booleanStates ? 1 : 0));
}
public static final Parcelable.Creator<SaveInstanceState> CREATOR = new Parcelable.Creator<SaveInstanceState>() {
#Override
public SaveInstanceState createFromParcel(Parcel in) {
return new SaveInstanceState(in);
}
#Override
public SaveInstanceState[] newArray(int size) {
return new SaveInstanceState[size];
}
};
}
in Activity i'm try to save into class by:
private ArrayList<SaveInstanceState> InstanceStateList;
public class ActivityMainView ... {
if (savedInstanceState == null || !savedInstanceState.containsKey("ActivityMain")) {
InstanceStateList = new ArrayList<SaveInstanceState>();
InstanceStateList.add(new SaveInstanceState(mLastMenuItemSelected));
InstanceStateList.add(new SaveInstanceState(mIsShowingExitDialogs));
} else
InstanceStateList = savedInstanceState.getParcelableArrayList("ActivityMain");
}
now for this blow function i can not get from Parcable class and restore savedInstanceState from it
public void RestoreInstanceState(Bundle savedInstanceState) {
savedInstanceState.getParcelableArrayList("ActivityMain");
}
whats my code problem?

Send an object to another activity using parcelable

I'm trying to send an object of this class to another activity. I used parcelabler.com to generate the code. The problem is when i declare the intent, Eclispse says that the method putExtra(String, GrupoMuscular) is undefined for the type Intent. Do i have a wrong parcelable implementation?
public class GrupoMuscular implements Parcelable {
private int id;
private static int id_aux = 0;
private String nome;
private int imagem;
private ArrayList<Exercicio> exercicios;
public GrupoMuscular(String nome, int img) {
//super();
id = id_aux;
id_aux++;
this.nome = nome;
this.imagem = img;
this.exercicios = new ArrayList<Exercicio>();
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public int getImagem() {
return imagem;
}
public void setImagem(int imagem) {
this.imagem = imagem;
}
public ArrayList<Exercicio> getGruposMuscular() {
return exercicios;
}
public void addExercicio(int id, String nome, String descricao, int imagem){
Exercicio ex = new Exercicio(id, nome, descricao, imagem);
exercicios.add(ex);
}
public void setGruposMuscular(ArrayList<Exercicio> gruposMuscular) {
this.exercicios = gruposMuscular;
}
public ArrayList<Exercicio> getExercicios() {
return exercicios;
}
public void setExercicios(ArrayList<Exercicio> exercicios) {
this.exercicios = exercicios;
}
public int getId() {
return id;
protected GrupoMuscular(Parcel in) {
id = in.readInt();
nome = in.readString();
imagem = in.readInt();
if (in.readByte() == 0x01) {
exercicios = new ArrayList<Exercicio>();
in.readList(exercicios, Exercicio.class.getClassLoader());
} else {
exercicios = null;
}
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(nome);
dest.writeInt(imagem);
if (exercicios == null) {
dest.writeByte((byte) (0x00));
} else {
dest.writeByte((byte) (0x01));
dest.writeList(exercicios);
}
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<GrupoMuscular> CREATOR = new Parcelable.Creator<GrupoMuscular>() {
#Override
public GrupoMuscular createFromParcel(Parcel in) {
return new GrupoMuscular(in);
}
#Override
public GrupoMuscular[] newArray(int size) {
return new GrupoMuscular[size];
}
};
}
Activity Intent:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent;
intent = new Intent(ExerciciosActivity.this, ListaExerciciosActivity.class);
intent.putExtra("musculos", gruposMusculares.get(position));
startActivity(intent);
}});
}
Try Passing the Object as a Parcelable Extra on the Intent.
http://developer.android.com/reference/android/content/Intent.html#putExtra(java.lang.String,android.os.Parcelable)
Since you are only passing a single instance of this Object.
// Create a new Intent
Intent myNewIntent = new Intent(this, NextActivity.class);
myNewIntent.putExtra("musculos", groupMusculares.get(position));
startActivity(myNewIntent);
Then in your NextActivity.class:
use
http://developer.android.com/reference/android/content/Intent.html#getParcelableExtra(java.lang.String)
// Class Member variable
GrupoMuscular mMuscleGroup;
// inside onCreate
Bundle extras = getIntent().getExtras();
// If the extras are not null
if(extras != null){
mMuscleGroup = extras.getParcelableExtra("musculos");
// if its not null do something with it
if(mMuscleGroup != null){
// Perform some logic
// ...
}
}

Not able to pass parcelable object ArrayList to a fragment activity

I have a Activity A which has a ArrayList of object which i parceable..
Object is :
public class DashBoardPOJO implements Parcelable {
private String dashBoardName;
private String dashBoardId;
private String dashBoardStatus;
private ArrayList<DashBoardDataPOJO> dashBoardDataList;
private boolean loaded;
public ArrayList<DashBoardDataPOJO> getDashBoardDataList() {
return dashBoardDataList;
}
public void setDashBoardDataList(
ArrayList<DashBoardDataPOJO> dashBoardDataList) {
this.dashBoardDataList = dashBoardDataList;
}
public boolean isLoaded() {
return loaded;
}
public void setLoaded(boolean loaded) {
this.loaded = loaded;
}
public String getDashBoardStatus() {
return dashBoardStatus;
}
public void setDashBoardStatus(String dashBoardStatus) {
this.dashBoardStatus = dashBoardStatus;
}
#Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(dashBoardName);
dest.writeString(dashBoardId);
dest.writeList(dashBoardDataList);
}
public static final Parcelable.Creator<DashBoardPOJO> CREATOR = new Parcelable.Creator<DashBoardPOJO>() {
public DashBoardPOJO createFromParcel(Parcel in) {
return new DashBoardPOJO(in);
}
public DashBoardPOJO[] newArray(int size) {
return new DashBoardPOJO[size];
}
};
public DashBoardPOJO() {
dashBoardName = null;
dashBoardId = null;
dashBoardDataList = null;
/*
* userName=null; userId=null;
*/
}
private DashBoardPOJO(Parcel in) {
dashBoardName = in.readString();
dashBoardId = in.readString();
in.readList(dashBoardDataList, null);
}
// GETTERS AND SETTERS............
public String getDashBoardName() {
return dashBoardName;
}
public void setDashBoardName(String dashBoardName) {
this.dashBoardName = dashBoardName;
}
public String getDashBoardId() {
return dashBoardId;
}
public void setDashBoardId(String dashBoardId) {
this.dashBoardId = dashBoardId;
}
}
I want to pass the ArrayList to a activity which extends Fragment Activity.
I am sending the object like this
Intent intent = new Intent(
DashboardActivity.this,
BaseFragmentActivity.class);
intent.putParcelableArrayListExtra("dashBoardList", dashBoardList);
startActivity(intent);
And receiving it at the fragment activity like this
dashboardList = getIntent().getExtras().getParcelableArrayList("dashBoardList");
But still the intent is returninig me a null value... Pls help...
Try this:
private DashBoardPOJO(Parcel in) {
dashBoardName = in.readString();
dashBoardId = in.readString();
dashBoardDataList = (ArrayList<DashBoardDataPOJO>) in.readArrayList(DashBoardDataPOJO.class.getClassLoader());
}

Categories

Resources