Nick Robertson
Nick Robertson

Reputation: 1047

Deserialize an array of Image Objects

I have the following class:

public class DetailedProduct implements Serializable {
    //attributes + get and set
    private Colour colour;
    //get+set

  public class Colour implements Serializable{
     private ArrayList<Image> images;
    //get+set

    public Image[] getImages() {
      return images.toArray(new Image[images.size()]);
    }
  }

  public class Image implements Serializable{

    private static final long serialVersionUID = 3460333138445770749L;
    private String image1;
    private String image2;
    private String image3;

        //get/set methods
  }
 }

I created afterwards an Intent as following

  DetailedProduct.Colour mCurrentColour;
  Intent myIntent = new Intent(DetailsActivity.this, ImageGallery.class);
  myIntent.putExtra("Images", mCurrentColour.getImages());
  startActivity(myIntent);

In the ImageGallery class now I tried the following code:

   Serializable extras = getIntent().getSerializableExtra("Images");
    if (extras != null) {
        images = (Image[]) extras;
    }

But I'm taking the following exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{com./com.productdetails.ProductImageGallery}: java.lang.ClassCastException: java.lang.Object[] cannot be cast to com.productdetails.DetailedProduct$Image[]

How can I cast correctly the serializable to an array of Image

Upvotes: 2

Views: 378

Answers (4)

Raffaele
Raffaele

Reputation: 20885

The Android runtime fails to serialize the array. The array type still implements Serializable, but when it comes back from the Bundle used by the Intent, it has lost all of its information (including type, which is always Ljava.lang.Object. Some answers on the internet suggest using Parcelable, however I tried and did not succeded myself.

What can be accomplished is transmitting a collection of Parcelable objects, but in the form of an ArrayList, which also happens to be the data structure you use in your original sample. The calling code looks like this:

Intent intent = new Intent(this, Target.class);
ArrayList<Foo> data = new ArrayList<Foo>();
data.add(new Foo());

intent.putParcelableArrayListExtra("data", data);
intent.putExtra("serializable", new Foo[] {new Foo()});
startActivity(intent);

I employed the usual dummy class named Foo, but note that implementing Parcelable is quite tedious. Moreover, it requires your class to have a static field named CREATOR of type Parcelable.Creator<T>, and with inner types this is not possible at all in the Java language. That's why you'll have to switch to nested (static) classes, eventually passing your current outer instance in the constructor and changing fields visibilty accordingly (from private to public or package-private). By the way, this will also improve testability of your codebase, because you reduce coupling. What I mean is, instead of this uncompilable source:

public class Product implements Parcelable {
  public class Color implements Parcelable {
    public static final Parcelable.Creator<Color> CREATOR; // Illegal!!!
  }
}

something like this

public class Product implements Parcelable{
  public static class Color implements Parcelable {
    public Color(Product exOuter) {
    }
  }
}

but note that this way you won't be able to access non-static members of the enclosing class, thus it may be better to move Color out of Product.

Upvotes: 0

Festus Tamakloe
Festus Tamakloe

Reputation: 11310

You cast is not correct

 java.lang.ClassCastException: java.lang.Object[] cannot be cast to com.productdetails.DetailedProduct$Image[]

You give a ListArray to intent and you try to cast it with array

this line are not correct

 if (extras != null) {
        images = (Image[]) extras;
    }

replace with

 if (extras != null) {
        images = (ListArray<Image>) extras;
    }

Upvotes: 0

akhiljayaram
akhiljayaram

Reputation: 141

You passed the images as an arrayList. But you are taking it as an array..

Use the following code

Serializable extras = getIntent().getSerializableExtra("Images");
    if (extras != null) {
        images = (ArrayList<Image>) extras;
    }

Upvotes: 0

Calvin Park
Calvin Park

Reputation: 1174

From quick thought, you can simply make the images into bytearray[], and since bite arrays primitive types which is serializable.

Upvotes: 0

Related Questions