【问题标题】:Android Parcelable ArraylistAndroid Parcelable Arraylist
【发布时间】:2016-06-20 10:40:53
【问题描述】:

我正在制作一个非营利慈善应用程序。尽管我在堆栈和谷歌中检查了许多问题,但我无法解决问题。
我有 3 节课:
- BaseCell 实现 Parcelable(基类)
- Needy 扩展 BaseCell
- 包含所有类列表的 UserBasket 类扩展 BaseCell

问题

我在 UserBasket 类中使用 Arraylist 持有 Needy 类。当我将它发送到另一个活动时,如果我向 UserBasket 添加 1 个项目,我会得到荒谬的结果(缺少或错误的字符),如果我添加超过 1 个项目,那么我会遇到异常。
我需要将 UserBasket 类(需要的物品列表)传递给付款活动,以便我可以计算慈善事业的总价格并执行必要的操作。

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;
}


}


需要

    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);
 }
}


用户篮

    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);
}

}


使用 MainActivity

中的项目发送 userBasket arrayList Navigate.navigateToPaymentPayuStart (MainActivity.this,userBasket,"basket"); // 带有“basket”键的 userBasket 数组列表
在 paymentPayu 活动中接收 UserBasket
UserBasket userBasket = getIntent().getParcelableExtra("basket");
我将如何在 paymentPayuActivity 中正确获取 UserBasket。
感谢您的帮助
谢谢。

【问题讨论】:

    标签: java android arraylist parcelable


    【解决方案1】:

    您似乎在处理 Parcelable 实现错误。即您正在从Parcel 读取一些变量两次,这是不允许的。因此,为了改进这一点,我们将尝试使您的代码更简单一些。由于Needy 实际上没有任何变量,让BaseCell 处理所有可打包的实现似乎更好,我已经尝试为您创建一个模拟,所以根据您的其余代码可能需要一个一点调整。

    首先我删除了Needy 中的所有Parcelable 实现,只是将它的CREATOR 指向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";
        }
    
    }
    

    然后我们将让BaseCell 处理所有Parcelable 实现,如下所示:

    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);
        }
    
    }
    

    【讨论】:

    • 我不知道你的 Qurban 类是什么样的,所以我不能保证上面的代码会 100% 工作。
    • 谢谢,我会用 BaseCell 尝试更多。
    • Qurban 只是从 Basecell 扩展的另一个类,但是,我没有在 userBasket 中添加任何 Qurban 类。
    • 没问题。顺便说一句,如果您使用的是 Android Studio,有一个名为“Android Parcelable 代码生成器”的插件会为您生成样板代码。这是一个非常方便的工具。您可以在“首选项 -> 插件”中找到它,然后搜索它:-)
    • 如果我在 Qurban 类中有一个额外的 arrayList,我可以将该 arraylist 写入 Parcel,因为当我需要在 Qurban 类中再次写入它时,我遇到了错误,就像你在第二次写入之前所说的那样parcel 是不允许的,所以有没有办法实现只属于 Qurban 类的 arraylist,需要在 Qurban 类中传递 BaseClass + arraylist 中的所有属性。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2014-04-22
    • 2012-06-12
    • 2019-07-30
    • 2017-07-27
    • 1970-01-01
    • 1970-01-01
    • 2019-07-30
    • 1970-01-01
    相关资源
    最近更新 更多