Android 类 Parcelable 与 ArrayList

Posted

技术标签:

【中文标题】Android 类 Parcelable 与 ArrayList【英文标题】:Android Class Parcelable with ArrayList 【发布时间】:2014-04-22 04:27:19 【问题描述】:

我有一个 android 项目,我有一个类。那个班级是ArrayList<Choices>。我将获取一些 XML,将其解析出来,然后从中生成对象,然后将其传递给另一个活动。我为此选择 Parcelable。

Parcelable 是一个不错的选择吗?我做的一切正确吗?我对 Parcelable 并不熟悉。我的 ArrayList 是我在这个类中创建的另一个类。它会正确地将对象的 ArrayList 传递给 Parcel,而不会扩展 Parcelable 和其他东西吗?

import java.util.ArrayList;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.os.ParcelableCompat;

public class Question implements Parcelable


String id;
String text;
String image;
ArrayList<Choices> CHOICES;


public Question(String id, String text, String image) 
    super();
    this.id = id;
    this.text = text;
    this.image = image;


public String getId() 
    return id;


public void setId(String id) 
    this.id = id;


public String getText() 
    return text;


public void setText(String text) 
    this.text = text;


public String getImage() 
    return image;


public void setImage(String image) 
    this.image = image;


@Override
public String toString() 
    return "Question [id=" + id + ", text=" + text + ", image=" + image
            + "]";





// Answer Choices class
class Choices 

    boolean isCorrect;
    String choice;

    public Choices(boolean isCorrect, String choice) 
        this.isCorrect = isCorrect;
        this.choice = choice;
    

    public String getChoice() 
        return choice;
    

    public boolean getIsCorrect() 
        return isCorrect;
    

    @Override
    public String toString() 
        return "Choices [isCorrect=" + isCorrect + ", choice=" + choice
                + "]";
    




public static final Parcelable.Creator<Question> CREATOR = new Parcelable.Creator<Question>() 

    @Override
    public Question createFromParcel(Parcel in) 
        return new Question(in);
    

    @Override
    public Question[] newArray(int size) 
        return new Question[size];
    

;

@Override
public int describeContents() 
    // TODO Auto-generated method stub
    return 0;


@Override
public void writeToParcel(Parcel dest, int flags) 

    dest.writeString(id);
    dest.writeString(text);
    dest.writeString(image);
    dest.writeList(CHOICES);



private Question(Parcel in) 
    this.id = in.readString();
    this.text = in.readString();
    this.image = in.readString();
    this.CHOICES = in.readArrayList(Choices.class.getClassLoader());



感谢您的帮助!

【问题讨论】:

【参考方案1】:

如果您需要在活动之间传递ArrayList,那么我也会实施Parcelable,因为我猜没有其他办法。 但是,我认为您不需要那么多 getter 和 setter。这是实现ParcelableQuestion 类:

public class Question implements Parcelable 
    public String id;
    public String text;
    public String image;
    public ArrayList<Choice> choices;


    /**
     * Constructs a Question from values
     */
    public Question (String id, String text, String image, ArrayList<Choice> choices) 
        this.id = id;
        this.text = text;
        this.image = image;
        this.choices = choices;
    

    /**
     * Constructs a Question from a Parcel
     * @param parcel Source Parcel
     */
    public Question (Parcel parcel) 
        this.id = parcel.readString();
        this.text = parcel.readString();
        this.image = parcel.readString();
        this.choices = parcel.readArrayList(null);
    

    @Override
    public int describeContents() 
        return 0;
    

    // Required method to write to Parcel
    @Override
    public void writeToParcel(Parcel dest, int flags) 
        dest.writeString(id);
        dest.writeString(text);
        dest.writeString(image);
        dest.writeList(choices);
    

    // Method to recreate a Question from a Parcel
    public static Creator<Question> CREATOR = new Creator<Question>() 

        @Override
        public Question createFromParcel(Parcel source) 
            return new Question(source);
        

        @Override
        public Question[] newArray(int size) 
            return new Question[size];
        

    ;

【讨论】:

我拥有的 ArrayList 怎么样,我的 Question 课程中还可以有这个课程吗?放在我的包裹里? 没有。与其他答案中的建议类似,您必须创建一个单独的 Choice 类并将其作为属性添加到 Question 类。 (就像idtext。) 好的,我将把 Choice 移到它的单独类中。那么你是说我可以从那个类中调用列表并将其添加到parcelable?我将如何“将其添加为属性”? @Kenny:我编辑了答案,包括如何将Choice 列表添加到Question 类。 谢谢@kenny。只需添加以下信息。当我添加“choices = parcel.readArrayList(Choice.class.getClassLoader());”时,它对我有用。以下对我不起作用“parcel.readArrayList(null)”。【参考方案2】:

您几乎拥有它,但不完全是,对。 Question 类看起来几乎正确 Parcelable。唯一行不通的就是将 Choices 数组打包。

有两种方法可以做到:

    使选择可打包。您必须添加所有必需的方法和 CREATOR。因为 Android 知道如何对 Parcelables 的 ArrayLists 进行打包,所以这将起作用。 将选择数组打包成为问题打包的一部分。为此,您可能会将数组的大小推入 Parcel,然后遍历 Choices,推入它们的值。另一方面,您将首先读取计数,然后读取每个选项的值,创建每个选项并将其推送到新问题中。

【讨论】:

您好成功地使用了选项 2(存储数组列表大小并在从包中写入/读取期间进行迭代),特别是当我为数组列表对象使用内部静态类时,它本身具有嵌套的数组列表对象.相当长的课程,但更喜欢把它们放在一起!看到所有使用 Parcelable 接口的单个​​对象与一个类迭代数组列表对象并放入包裹中的性能差异会很有趣。【参考方案3】:

用途:

in.createTypedArrayList(Product.CREATOR)

在将 Parable 对象作为参数的构造函数中。

在 writeToParcel 方法中使用dest.writeTypedList(product);

【讨论】:

【参考方案4】:

为“Choices”创建一个新的 java 文件并实现“Parcelable”。如果您不实现 parcelable,您将获得运行时异常(无法编组)。所以使用下面的代码:

    public class Choices implements Parcelable

        boolean isCorrect;
        String choice;

        public Choices(boolean isCorrect, String choice) 
            this.isCorrect = isCorrect;
            this.choice = choice;
        
        //Create getters and setters 

        protected Choices(Parcel in) 
            isCorrect = in.readByte() != 0;
            choice = in.readString();
        

        public static final Creator<Choices> CREATOR = new Creator<Choices>() 
            @Override
            public Choices createFromParcel(Parcel in) 
                return new Choices(in);
            

            @Override
            public Choices[] newArray(int size) 
                return new Choices[size];
            
        ;

        @Override
        public String toString() 
            return "Choices [isCorrect=" + isCorrect + ", choice=" + choice
                    + "]";
        

        @Override
        public int describeContents() 
            return 0;
        

        @Override
        public void writeToParcel(Parcel dest, int flags) 
            dest.writeByte((byte) (isCorrect ? 1 : 0));
            dest.writeString(choice);
        
    

正如@G.Blake 在上面的回答中提到的,您需要使 Choices Parcelable 并且 Android 知道如何打包 Parcelables 的 ArrayLists

【讨论】:

以上是关于Android 类 Parcelable 与 ArrayList的主要内容,如果未能解决你的问题,请参考以下文章

android中用Intent传数据,如果用传递的是一个类,就将类实现Parcelable接口

Android Kotlin 创建类实现 Parcelable 在 writeToParcel 方法的“覆盖”中给出错误

X 类不是抽象的,没有实现 android.os.Parcelable 中定义的 fun writeToParcel()

有没有一种方便的方法可以使用 Kotlin 在 Android 中创建 Parcelable 数据类?

解组 Android Intent Parcelable 时找不到类

运行时异常:ClassCastException android.os.Bundle 无法转换为 Parcelable 类