1

I trying to pass array of objects via Parcelable. But after the transfer, the data is converted into something strange

The transmitting part:

for (int i=0; i<res.size(); i++) {
                Log.d(LOG_TAG, "id = "+res.get(i).id+" weigth = "+res.get(i).weight); 
            }

            ParcelableProducts Checked = new ParcelableProducts();
            Checked.setList(res);
            intent.putExtra(ParcelableProducts.class.getCanonicalName(), Checked);

The receiving part:

ParcelableProducts res = (ParcelableProducts) data.getParcelableExtra(ParcelableProducts.class.getCanonicalName());
            ArrayList<prProduct> prod = res.prod;
            for (int i=0; i<prod.size(); i++) {
                Log.d(LOG_TAG, "id = "+prod.get(i).id+" weigth = "+prod.get(i).weight); 
            }

Classes Parcelable with ArrayList:

public class ParcelableProducts implements Parcelable {
    final private static String LOG_TAG = "ParcelableProducts";
    public ArrayList<prProduct> prod;

    public ParcelableProducts() {
        prod = new ArrayList<prProduct>();
     }

    public void setList(ArrayList<prProduct> _prod){
        prod = _prod;
    }

    public ArrayList<prProduct> getList() {
        return prod;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeList(prod);
    }
    public static final Parcelable.Creator<ParcelableProducts> CREATOR = new Parcelable.Creator<ParcelableProducts>() {
        public ParcelableProducts createFromParcel(Parcel in) {
          return new ParcelableProducts(in);
        }

        public ParcelableProducts[] newArray(int size) {
          return new ParcelableProducts[size];
        }
      };

      private ParcelableProducts(Parcel parcel) {
        prod  = new ArrayList<prProduct>();
        parcel.readTypedList(prod, prProduct.CREATOR);
      }
}

and prProduct:

public class prProduct implements Parcelable {
      final static String LOG_TAG = "prProduct";

      public float weight;
      public int id;

      public prProduct(int _id, Float _weight) {
        weight = _weight;
        id = _id;
      }

      public int describeContents() {
        return 0;
      }

      public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeFloat(weight);
        parcel.writeInt(id);
      }

      public static final Parcelable.Creator<prProduct> CREATOR = new Parcelable.Creator<prProduct>() {
        public prProduct createFromParcel(Parcel in) {
          return new prProduct(in);
        }

        public prProduct[] newArray(int size) {
          return new prProduct[size];
        }
      };

      private prProduct(Parcel parcel) {
        weight = parcel.readFloat();
        id = parcel.readInt();
      }
}

in log:

Transmit: id = 7 weigth = 0.0

Recive: id = 7602278 weigth = 4.2E-44

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
ftp27
  • 885
  • 1
  • 12
  • 31
  • If your `prProduct` class isn't going to get any more complex, why don't you switch it to being `Serializable` instead of `Parcelable`? `ArrayList` is also `Serializable` so everything should work just fine. Let me know if this is an option and I'll post an answer detailing how to do it. – Michael Celey May 08 '13 at 03:55
  • Try reading from the parcel right after you create it, just to help localize the problem - is it in the parcel reading/creation, or the transmitting of the parcel between activities. – tbkn23 May 08 '13 at 04:26
  • MCeley, I need to pass one int and one float number. – ftp27 May 08 '13 at 05:41

2 Answers2

4

Off hand I don't see where the data is getting corrupted in transmission, but it will help to clean up your code. Personally I have fixed many weird bugs in the past when I refactor my code to improve readability. First thing you should do is remove the class "ParcelableProducts" because you don't need it. Just pass the ArrayList in the intent directly using the putParcelableArrayListExtra method. Shown here.

Also this is a bit nit picky but you shouldn't directly access your fields. It is better to set them as private and use getters/setters. Also using a for each loop for your logging statement would be a bit cleaner.

A safer PrProduct class.

//Java classes should start with capital letter
public class PrProduct implements Parcelable {
    private final static String LOG_TAG = "PrProduct";

    private float weight;
    private int id;

    public prProduct(int id, float weight) {
        this.weight = weight;
        this.id = id;
    }
    //Using getters only makes this immutable which is safer since the 
    //weight/id aren't likely to change.
    public float getWeight(){
        return weight;}
    public int getId(){
        return id;}

    public int describeContents() {
      return 0;
    }

    public void writeToParcel(Parcel parcel, int flags) {
      parcel.writeFloat(weight);
      parcel.writeInt(id);
    }

    public static final Parcelable.Creator<prProduct> CREATOR = new
      Parcelable.Creator<prProduct>() {
      public prProduct createFromParcel(Parcel in) {
        return new prProduct(in);
      }

      public prProduct[] newArray(int size) {
        return new prProduct[size];
      }
    };

    private prProduct(Parcel parcel) {
      weight = parcel.readFloat();
      id = parcel.readInt();
    }
}

//A sample for each loop
for(PrProduct product: prod)
    Log.d(LOG_TAG, "weight=" + product.getWeight() + " id=" + product.getId());
Erik
  • 103
  • 7
0

Why do you need to create the object ParcelableProducts that implements Parcelable? I think you can just pass the arraylist directly using putParcelableArrayListExtra method from the intent?

dtheo
  • 123
  • 5