Search code examples
javaandroidarraylistparcelable

Android Parcelable Arraylist


I am crafting a non profit charity app. Despite I have checked many questions in stack and google, i could not solve the problem.
I have 3 classes:
- BaseCell implements Parcelable (Base class)
- Needy extends BaseCell
- UserBasket class which hold the list of all classes extend BaseCell

Problem

I am holding Needy classes with Arraylist in UserBasket class. When i send it to another activity, if i add 1 item to the UserBasket i am getting ridiculous result(Missing or wrong characters) and if i add more than 1 item then i am getting exception.
I need to deliver UserBasket class(list of needy items) to the payment activity so i can calculate the total price for charity and perform necessary actions.

public abstract class BaseCell implements Parcelable {


String imageUrl;
int percentageOfCollectedDonation;
String needyTitle;
String needyDescription;

protected String category;
protected int amountOfCollectedDonation=0;
protected int amountOfTargetDonation=0;
protected int amountOfDonater=0;
protected int drawableID;
protected String campaignCode;

protected int maxInstallmentNumber;

int price;

public String getCellType() {
    return cellType;
}

protected String cellType ;

/**
 * How many of this campaign purchased by user
 * */
protected int userPurchaseAmount = 1;

protected BaseCell(String cellType)
{
    this.cellType = cellType;
}
protected BaseCell(Parcel in)
{

    drawableID = in.readInt();
    price = in.readInt();
    imageUrl = in.readString();
    needyTitle = in.readString();
    needyDescription = in.readString();
    category = in.readString();
    campaignCode = in.readString();
    maxInstallmentNumber = in.readInt();
    userPurchaseAmount = in.readInt();
}

public static final Parcelable.Creator<BaseCell> CREATOR = new Parcelable.Creator<BaseCell>() {
    @Override
    public BaseCell createFromParcel(Parcel in) {
        String cellType = in.readString();
        BaseCell baseCell = null;

        if (cellType.equals("Needy"))
        {
            baseCell = (Needy)new Needy(in);
        }else
        if (cellType.equals("Qurban"))
        {
            baseCell = (Qurban)new Qurban(in);
        }

        return baseCell;
    }

    @Override
    public BaseCell[] newArray(int size) {
        return new BaseCell[size];
    }
};
public void writeToParcel(Parcel out, int flags) {
    out.writeString(getCellType());
}


public BaseCell(String imageUrl, int drawableID, String needyTitle, String needyDescription, int amountOfCollectedDonation, int amountOfTargetDonation, int amountOfDonater, String category,String campaignCode, int maxInstallmentNumber, int price)
{
    this.imageUrl = imageUrl;
    this.drawableID = drawableID;
    this.needyTitle = needyTitle;
    this.needyDescription = needyDescription;
    this.amountOfCollectedDonation = amountOfCollectedDonation;
    this.amountOfTargetDonation = amountOfTargetDonation;
    this.amountOfDonater = amountOfDonater;
    this.category = category;
    this.campaignCode = campaignCode;
    this.maxInstallmentNumber = maxInstallmentNumber;
    this.price= price;
}


}


Needy

    public class Needy extends BaseCell {

    protected Needy(Parcel in) {
    super(in);
    cellType ="Needy";
    }



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

    @Override
    public Needy[] newArray(int size) {
        return new Needy[size];
    }
};


public Needy(String imageUrl, int drawableID, String needyTitle, String needyDescription, int amountOfCollectedDonation, int amountOfTargetDonation, int amountOfDonater, String category, String campaignCode, int maxInstallmentNumber, int price) {

    super(imageUrl, drawableID, needyTitle, needyDescription, amountOfCollectedDonation, amountOfTargetDonation, amountOfDonater, category, campaignCode, maxInstallmentNumber,price);
    cellType = "Needy";
}


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

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(getCellType());
    super.writeToParcel(dest,flags);
    dest.writeInt(drawableID);
    dest.writeInt(price);
    dest.writeString(imageUrl);
    dest.writeString(needyTitle);
    dest.writeString(needyDescription);
    dest.writeString(category);
    dest.writeString(campaignCode);
    dest.writeInt(maxInstallmentNumber);
    dest.writeInt(userPurchaseAmount);
}

@Override
public void setUserPurchaseAmount(int userPurchaseAmount) {
    super.setUserPurchaseAmount(userPurchaseAmount);
 }
}


UserBasket

    public class UserBasket implements Parcelable{


List<BaseCell> userBasket;

/**
 * holds all items to be purchased
 * */
public UserBasket(List<BaseCell> userBasket) {
    this.userBasket = userBasket;
}

public UserBasket() {
    userBasket = new ArrayList<>();
}


protected UserBasket(Parcel in) {
    super();
    setUserBasket(new ArrayList<BaseCell>());
    userBasket = in.createTypedArrayList(BaseCell.CREATOR);
    //in.readTypedList(userBasket,BaseCell.CREATOR);
}

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

    @Override
    public UserBasket[] newArray(int size) {
        return new UserBasket[size];
    }
};

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

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeTypedList(userBasket);
}



public List<BaseCell> getUserBasket() {
    return userBasket;
}

public void setUserBasket(List<BaseCell> userBasket) {
    this.userBasket = userBasket;
}

/**
 * Add to the basket list
 * */
public void add(Needy donation) {
    if (donation != null)
        userBasket.add(donation);
}

/**
 * Remove from basket list
 * */
public void remove(int position)
{
    if (userBasket.size()>0)
        userBasket.remove(position);
}

}


sending userBasket arrayList with items from MainActivity

Navigate.navigateToPaymentPayuStart (MainActivity.this,userBasket,"basket"); // userBasket arrayList with "basket" key
Receiving UserBasket in paymentPayu activity
UserBasket userBasket = getIntent().getParcelableExtra("basket");
How am i going to get UserBasket properly in paymentPayuActivity.
I appreciate for the help
Thank you.


Solution

  • It does seem like you are handling the Parcelable implementation wrong. e.i. you are reading some of the variables from the Parcel twice, which isn't allowed. So to improve this, we'll try to make your code a bit simpler. As Needy doesn't actually have any variables, it seems better to let BaseCell handle all of the parcelable implementation, i've tried to create a mock for you, so depending on the rest of your code it might need a bit of tweaking.

    First i've removed all of the Parcelable implementation in Needy and is just pointing it's CREATOR to BaseCell.

    public class Needy extends BaseCell {
    
        protected Needy(Parcel in) {
            super(in);
            cellType ="Needy";
        }
    
        // Since Needy doesn't actually store any variables, we don't need a Creator for it.
        // Just point it to BaseCell.CREATOR and let it handle it
        public static final Parcelable.Creator<BaseCell> CREATOR = BaseCell.CREATOR;
    
        public Needy(String imageUrl, int drawableID, String needyTitle, String needyDescription, int amountOfCollectedDonation, int amountOfTargetDonation, int amountOfDonater, String category, String campaignCode, int maxInstallmentNumber, int price) {
            super(imageUrl, drawableID, needyTitle, needyDescription, amountOfCollectedDonation, amountOfTargetDonation, amountOfDonater, category, campaignCode, maxInstallmentNumber,price);
            cellType = "Needy";
        }
    
    }
    

    And then we'll let BaseCell handle all of the Parcelable implementation, like so:

    public abstract class BaseCell implements Parcelable {
    
        /**
         * ALL OF YOUR VARIABLES, GETTERS, SETTERS AND CONSTRUCTORS GOES HERE
         */
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        public static final Parcelable.Creator<BaseCell> CREATOR = new Parcelable.Creator<BaseCell>() {
            @Override
            public BaseCell createFromParcel(Parcel in) {
                String cellType = in.readString();
                if (cellType.equals("Needy")) {
                    return (Needy)new Needy(in);
                } else if (cellType.equals("Qurban")) {
                    return (Qurban)new Qurban(in);
                }
                return null;
            }
    
            @Override
            public BaseCell[] newArray(int size) {
                return new BaseCell[size];
            }
        };
    
        protected BaseCell(Parcel in) {
            drawableID = in.readInt();
            price = in.readInt();
            imageUrl = in.readString();
            needyTitle = in.readString();
            needyDescription = in.readString();
            category = in.readString();
            campaignCode = in.readString();
            maxInstallmentNumber = in.readInt();
            userPurchaseAmount = in.readInt();
        }
    
        public void writeToParcel(Parcel out, int flags) {
            // cellType written first, and read by Creator
            out.writeString(cellType);
            // the rest is read by the BaseCell constructor
            out.writeInt(drawableID);
            out.writeInt(price);
            out.writeString(imageUrl);
            out.writeString(needyTitle);
            out.writeString(needyDescription);
            out.writeString(category);
            out.writeString(campaignCode);
            out.writeInt(maxInstallmentNumber);
            out.writeInt(userPurchaseAmount);
        }
    
    }