Passing an ArrayList of other Arrays to an Activity - java

I have an arraylist of custom objects that extend the Parecelable class and can thus be sent to an Activity through a bundle or through a localbroadcast manager.
Now, my problem arises when i try to send an arraylist of other arrays i.e ArrayList<ArrayList<my_custom_object>>. How can i achieve this?

1.Custom parcelable class (replacing with your custom parcelable class):
import android.os.Parcel;
import android.os.Parcelable;
/**
* Custom parcelable class
*/
public class MyParcelable implements Parcelable {
public int data;
public MyParcelable(int data) {
this.data = data;
}
private MyParcelable(Parcel source) {
// Reading custom data
data = source.readInt();
}
public static final Parcelable.Creator<MyParcelable> CREATOR
= new Parcelable.Creator<MyParcelable>() {
#Override
public MyParcelable createFromParcel(Parcel source) {
return new MyParcelable(source);
}
#Override
public MyParcelable[] newArray(int size) {
return new MyParcelable[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
// Saving custom data
dest.writeInt(data);
}
}
2.Implement a Parcelable class which extends ArrayList.
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
/**
* ArrayList of the custom parcelable object
*/
public class MyParcelableList extends ArrayList<MyParcelable> implements Parcelable {
public MyParcelableList() {
}
private MyParcelableList(Parcel source) {
for (Parcelable p : source.readParcelableArray(MyParcelable.class.getClassLoader()))
add((MyParcelable) p);
}
public static final Parcelable.Creator<MyParcelableList> CREATOR
= new Parcelable.Creator<MyParcelableList>() {
#Override
public MyParcelableList createFromParcel(Parcel source) {
return new MyParcelableList(source);
}
#Override
public MyParcelableList[] newArray(int size) {
return new MyParcelableList[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelableArray(toArray(new MyParcelable[size()]), flags);
}
}
3.Passing Intent to TargetActivity.
// Preparing data ...
MyParcelableList list1 = new MyParcelableList();
list1.add(new MyParcelable(1));
MyParcelableList list2 = new MyParcelableList();
list2.add(new MyParcelable(2));
list2.add(new MyParcelable(3));
ArrayList<MyParcelableList> listOfList = new ArrayList<>();
listOfList.add(list1);
listOfList.add(list2);
// Send intent to your target activity
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("KEY_OF_EXTRA", listOfList);
context.startActivity(new Intent(context, TargetActivity.class).putExtras(bundle));
4.Retrieve data at TargetActivity.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
// processing intent data
if (getIntent()!=null) {
Bundle bundle = getIntent().getExtras();
if (bundle.containsKey("KEY_OF_EXTRA")) {
ArrayList<MyParcelableList> listOfList = bundle.getParcelableArrayList("KEY_OF_EXTRA");
if (listOfList != null)
// Do something here ...
for (MyParcelableList list : listOfList) {
for (MyParcelable p : list) {
Log.v("TargetActivity", "p.data=" + p.data);
}
}
}
}
}

You can try the following code
ActivityA send:
ArrayList<ArrayList<CustomClass>>data = new ArrayList<ArrayList<CustomClass>>();
ArrayList<CustomClass>d1 = new ArrayList<CustomClass>();
CustomClass temp = new CustomClass("this is my object");
d1.add(temp);
data.add(d1);
Intent intent = new Intent(JumpToMainActivity.ACTION);
intent.putExtra("data",data);
startActivity(intent);
ActivityB get:
Intent intent = getIntent();
ArrayList<ArrayList<CustomClass>>data = (ArrayList<ArrayList<CustomClass>>) intent.getSerializableExtra("data");
ArrayList<CustomClass>d1 = data.get(0);
System.out.println("received:" + d1.get(0).result);
CusstonClass.java:
/**
* Created by obo on 15/10/23.
*/
public class CustomClass implements Parcelable {
public String result = "this is my object";
public CustomClass(String result){this.result = result;};
protected CustomClass(Parcel in) {
result = in.readString();
}
public static final Creator<CustomClass> CREATOR = new Creator<CustomClass>() {
#Override
public CustomClass createFromParcel(Parcel in) {
return new CustomClass(in);
}
#Override
public CustomClass[] newArray(int size) {
return new CustomClass[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(result);
}
}
Hope to help you

Related

How do I iterate through an ArrayList of custom objects from Intent and add them into LinearLayout?

I have an ArrayList of custom FlightData objects within the intent. I load the intent and get the arraylist as null, and the foreach loop also forces me to use Object as type.
Saving arraylist into intent:
intent.putParcelableArrayListExtra("FlightDataList", (ArrayList<? extends Parcelable>) flightDataList);
Loading of intent:
Intent intent = getIntent();
LinearLayout layout_datasheet = findViewById(R.id.layout_datasheet);
List flightDataList = intent.getParcelableArrayListExtra("FlightDataList");
if (flightDataList == null){
Log.d("flightDataList_size", "FlightDataList is null"); // this fires
}
assert flightDataList != null;
for (Object data : flightDataList){
data = (FlightData) data; // items in list are of type FlightData
TextView tv = new TextView(this);
tv.setText(data.toString());
layout_datasheet.addView(tv);
}
My custom class' parcelable functions (x,y,time, has getters-setters):
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeDouble(x);
dest.writeDouble(y);
dest.writeDouble(time);
}
public static final Creator<FlightData> CREATOR = new Creator<FlightData>() {
#Override
public FlightData createFromParcel(Parcel in) {
return new FlightData(in);
}
#Override
public FlightData[] newArray(int size) {
return new FlightData[size];
}
};
1.First Implement Parceable in your FlightData object model / pojo / class
2.val flightDataList= ArrayList<FlightData>()
3.val args = Bundle()
4.args.putParcelableArrayList("FlightDataList", flightDataList)
5.intent.putExtra(args)
Then to get list
val flightDataList = context.getIntent().getExtras().getParcelableArrayList("FlightDataList")
I doubt that you have implemented Parcable in FlightData
https://medium.com/techmacademy/how-to-implement-and-use-a-parcelable-class-in-android-part-1-28cca73fc2d1
It should work. The only thing that I am missing in your example is the constructor. It could explain the null your are getting.
Try adding this constructor for FlightData
public FlightData(Parcel in) {
x = in.readDouble();
y = in.readDouble();
time = in.readDouble();
}
did you try creating a datastructure that implements parcelable?
public class flightDataList implements Parcelable{
String dataThingyString;
int dataThingyInt;
public flightDataList(String dataThingyString, int dataThingyInt){
this.dataThingyString = dataThingyString;
this.dataThingyInt = dataThingyInt;
}
public flightDataList(Parcle in){
this.dataThingyString = in.readString();
this.dataThingyInt = in.readInt();
}
#Override
public void writeToParcel(Parcel dest, int flags){
dest.writeString(dataThingyString);
dest.writeInt(dataThingyInt);
}
public static final Creator<flightDataList> CREATOR = new Creator<flightDataList>(){
#Override
public flightDataList createFromParcel(Parcel source){
return new flightDataList(source);
}
#Override
public flightDataList[] newArray(int size){
return new flightDataList[size];
}
}
public void setdataThingyString(String stringData){
this.dataThingyString = stringData;
}
public void setdataThingyInt(int intData){
this.dataThingyInt = intData;
}
public String getdataThingyString(){
return dataThingyString;
}
public int getdataThingyInt(){
return dataThingyInt;
}
#Override
public int describeContents(){
return 0;
}
}

Parcelable list inside Parcelable class not reading back with Parcel.readTypedList

I have two Activities, A and B. I am trying to send object from Activity A, to Activity B. When in Activity A, I can see that my List contains two items, but when I retrieve it in Activity B, the List contains 7000000+ records.
Here is my Assessment class, that implements Parcelable, and contains an ArrayList<Photo> which should be parcelable as well.
Assessment POJO:
public class Assessment extends BaseObservable implements Parcelable {
public Assessment(){
}
#SerializedName("Vehicle")
private String vehicle;
#SerializedName("Photos")
private List<Photo> photos;
#Bindable
public String getVehicle() {
return vehicle;
}
public void setVehicle(String vehicle) {
this.vehicle = vehicle;
notifyPropertyChanged(BR.vehicle);
}
public List<Photo> getPhotos() {
return photos;
}
public void setPhotos(List<Photo> photos) {
this.photos = photos;
}
protected Assessment(Parcel in) {
vehicle = in.readString();
photos = new ArrayList<Photo>();
in.readTypedList(photos, Photo.CREATOR);
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(vehicle);
dest.writeTypedList(photos);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<Assessment> CREATOR = new Parcelable.Creator<Assessment>() {
#Override
public Assessment createFromParcel(Parcel in) {
return new Assessment(in);
}
#Override
public Assessment[] newArray(int size) {
return new Assessment[size];
}
};
}
Photo POJO:
public class Photo implements Parcelable {
public Photo(){
}
#SerializedName("PhotoPath")
private String photoPath;
public String getPhotoPath() {
return photoPath;
}
public void setPhotoPath(String photoPath) {
this.photoPath = photoPath;
}
#SerializedName("Base64PhotoString")
private String photoBase64String;
public String getPhotoBase64String() {
return photoBase64String;
}
public void setPhotoBase64String(String photoBase64String) {
this.photoBase64String = photoBase64String;
}
protected Photo(Parcel in) {
photoPath = in.readString();
photoBase64String = in.readString();
}
//region parelable
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(photoPath);
dest.writeString(photoBase64String);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<Photo> CREATOR = new Parcelable.Creator<Photo>() {
#Override
public Photo createFromParcel(Parcel in) {
return new Photo(in);
}
#Override
public Photo[] newArray(int size) {
return new Photo[size];
}
};
//endregion
}
Here is how I send the object via Intent from Activity A, to Activity B:
public void OnAdapterItemClicked(View view){
Intent activityIntent = new Intent(this, com.example.andrewkp.gaassessing.DisplayAssessment.class);
Assessment extraAssessment = getAssessmentFromCollection(view); //extraAssessment.getPhotos().size() == 2
activityIntent.putExtra("assessment", extraAssessment);
startActivity(activityIntent);
}
And here is how I read the Parcelable object in Activity B:
assessment = getIntent().getExtras().getParcelable("assessment");
I have looked at the following article, and I follow exactly what they do, but my photos list does not persist through to Activity B:
When I debug the readTypedList method in Parcel class, I can see that it adds 7000000+ records to my ArrayList, but never removes them. Why is this behavior happening?
You are able to put up to 1MB of data in a Bundle encapsulated inside Intent.
You will get bunch of errors when sending PhotoBase64String in Bundle.
However, in order to overcome this issue, I would suggest path/URI of your photo to your second activity. Then in your second activity, read photo from that path, and perform your desired operation.

How to pass object with List of other object between activities using Parcelable?

I have an object called Order which I want to pass between activities. Currently I am using Parcelable to do so.
public class Order implements Parcelable {
private String email;
private Long timestamp;
private List<OrderItem> items;
public Order() { }
private Order(Parcel in) {
email = in.readString();
timestamp = in.readLong();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(email);
if (timestamp == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
dest.writeLong(timestamp);
}
dest.writeTypedList(items);
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<Order> CREATOR = new Creator<Order>() {
#Override
public Order createFromParcel(Parcel in) {
return new Order(in);
}
#Override
public Order[] newArray(int size) {
return new Order[size];
}
};
// Getters
...
}
The items field is a List of OrderItem objects which implement the Parcelable interface.
public class OrderItem implements Parcelable {
private String orderedClothingId;
private int quantity;
public OrderItem() { }
public OrderItem(String orderedClothingId, int quantity) {
this.orderedClothingId = orderedClothingId;
this.quantity = quantity;
}
private OrderItem(Parcel in) {
orderedClothingId = in.readString();
quantity = in.readInt();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(orderedClothingId);
dest.writeInt(quantity);
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<OrderItem> CREATOR = new Creator<OrderItem>() {
#Override
public OrderItem createFromParcel(Parcel in) {
return new OrderItem(in);
}
#Override
public OrderItem[] newArray(int size) {
return new OrderItem[size];
}
};
}
Now to pass an Order object called order from one activity to another I do the following:
Intent intent = new Intent(mContext, ActivityTwo.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra(ORDER_DETAIL_INTENT_EXTRA_KEY, order);
mContext.startActivity(intent);
In ActivityTwo I collect the Order object like so:
Bundle data = getIntent().getExtras();
assert data != null;
mOrder = data.getParcelable(ORDER_DETAIL_INTENT_EXTRA_KEY);
However, when I log the items field contained in the Order object in ActivityTwo it is null. How do I pass the original non-null Order object between activities without the items list being null?
First you miss to read the array back with dest = in.readTypedList(emptyList, CREATOR);
But second and more important, you need to write/read the same ammount of arguments, since you have a if in your writeToParcel you need the same when reading:
private Order(Parcel in) {
email = in.readString();
if(in.readByte() == 1)
timestamp = in.readLong(); //here to skip just like the writeToParcel
in.readTypedList(items = new ArrayList<OrderItem>(), OrderItem.CREATOR);
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(email);
if (timestamp == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
dest.writeLong(timestamp);
}
dest.writeTypedList(items);
}
From first glance it looks like you are passing different different keys within your parcelable
ORDER_DETAIL_INTENT_EXTRA_KEY in the first and CLOTHING_ADMIN_DETAIL_INTENT_EXTRA_KEY in the 2nd. They should both be the same, so pick which one.
Also you can use getIntent().getParcelableExtra() instead of having to use a Bundle

Android: Parcelable with inheritance

Now, I have three class, the base class is BaseWidget which implements Parcelable, two subclasses are SelectWidget and TextWidget. Then, I use a class named WidgetInfo (also implements Parcelable) to keep a list of BaseWidget or SelectWidget or TextWidget objects.
While I put WidgetInfo object into an Intent to start TestActivity, and I received WidgetInfo in TestActivity ,but all the elements of list (which in WidgetInfo) convert to BaseWidget object. And subclass object member variable is lost. What is problem???
BaseWidget.java:
public class BaseWidget implements Parcelable{
private String name;
public BaseWidget() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
protected BaseWidget(Parcel in) {
this.name = in.readString();
}
public static final Creator<BaseWidget> CREATOR = new Creator<BaseWidget>() {
#Override
public BaseWidget createFromParcel(Parcel in) {
return new BaseWidget(in);
}
#Override
public BaseWidget[] newArray(int size) {
return new BaseWidget[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
}
}
TextWidget.java:
public class TextWidget extends BaseWidget{
private String width = "100";
public TextWidget() {
}
public String getWidth() {
return width;
}
public void setWidth(String width) {
this.width = width;
}
protected TextWidget(Parcel in) {
super(in);
width = in.readString();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(width);
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<TextWidget> CREATOR = new Creator<TextWidget>() {
#Override
public TextWidget createFromParcel(Parcel in) {
return new TextWidget(in);
}
#Override
public TextWidget[] newArray(int size) {
return new TextWidget[size];
}
};
}
SelectWidget.java:
public class SelectWidget extends BaseWidget{
private int height = 200;
public SelectWidget() {
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
protected SelectWidget(Parcel in) {
super(in);
height = in.readInt();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(height);
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<SelectWidget> CREATOR = new Creator<SelectWidget>() {
#Override
public SelectWidget createFromParcel(Parcel in) {
return new SelectWidget(in);
}
#Override
public SelectWidget[] newArray(int size) {
return new SelectWidget[size];
}
};
}
WidgetInfo.java:
public class WidgetInfo implements Parcelable{
private List<BaseWidget> widgetList;
public WidgetInfo() {
}
public List<BaseWidget> getWidgetList() {
return widgetList;
}
public void setWidgetList(List<BaseWidget> widgetList) {
this.widgetList = widgetList;
}
protected WidgetInfo(Parcel in) {
widgetList = in.createTypedArrayList(BaseWidget.CREATOR);
}
public static final Creator<WidgetInfo> CREATOR = new Creator<WidgetInfo>() {
#Override
public WidgetInfo createFromParcel(Parcel in) {
return new WidgetInfo(in);
}
#Override
public WidgetInfo[] newArray(int size) {
return new WidgetInfo[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedList(widgetList);
}
}
start Intent:
WidgetInfo info = new WidgetInfo();
BaseWidget widget1 = new BaseWidget();
BaseWidget widget2 = new TextWidget();
BaseWidget widget3 = new SelectWidget();
List<BaseWidget> list = new ArrayList<>();
list.add(widget1);
list.add(widget2);
list.add(widget3);
info.setWidgetList(list);
Intent intent = new Intent(this, TestActivity.class);
intent.putExtra("widgetInfo", info);
startActivity(intent);

NullPointerException on Android Parcelable Object on Intent

I have this problem with this piece of code and I have been a few days trying to solve it and I can't find the solution.
I have this parcelable class:
public class Sistema implements Parcelable{
private ArrayList<Lista> listas;
private ArrayList<Articulo> articulos;
public Sistema() {
listas = new ArrayList<Lista>();
articulos = new ArrayList<Articulo>();
}
public ArrayList<Lista> getListas() {
return listas;
}
public void agregarLista(Lista lista) {
this.getListas().add(lista);
}
public ArrayList<Articulo> getArticulos(){
return this.articulos;
}
public void agregarArticulo(Articulo articulo){
this.getArticulos().add(articulo);
}
public static final Parcelable.Creator<Sistema> CREATOR =
new Parcelable.Creator<Sistema>() {
#Override
public Sistema createFromParcel(Parcel parcel) {
return new Sistema(parcel);
}
#Override
public Sistema[] newArray(int size) {
return new Sistema[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeTypedList(listas);
parcel.writeTypedList(articulos);
}
public Sistema(Parcel parcel)
{
parcel.readTypedList(listas, Lista.CREATOR);
parcel.readTypedList(articulos, Articulo.CREATOR);
}
}
And then in the main i use an intent to send a Sistema object to an other activity:
public void addArticle(View view) {
Intent intent = new Intent(this, AgregarArticulo.class);
intent.putExtra("objectSystem", s);
this.startActivityForResult(intent, 1);
}
Here is where the problem is, i recieve the intent in the second activity with this code:
Intent intento = getIntent();
s = intento.getParcelableExtra("objectSystem");
When I run the code, i get a NullPointerException in the getParcelableExtra
Do you guys have an idea of what the problem should be?
Thanks
Could you please try this . You need to prefix your package name(com.example.whatever) with the name your passing in putExtra:
public void addArticle(View view) {
Intent intent = new Intent(this, AgregarArticulo.class);
intent.putExtra("YOURPACKAGENAME.objectSystem", s);
this.startActivityForResult(intent, 1);
}
and same in getParcelableExtra also:
Intent intento = getIntent();
s = intento.getParcelableExtra("YOURPACKAGENAME.objectSystem");

Categories