如何创建可打包的二维可打包数组?

How to create a two dimensional parcelable array of parcelables?

我必须关注以下可打包对象:

    public class CGameCard implements Parcelable {
    ...

    private int mX;
    private int mY;
    private String mObjectName;
    private int mState;

    public CGameCard(int aX, int aY, String aObjectName) {
        mX = aX;
        mY = aY;
        mObjectName = aObjectName;
        mState = CARD_STATE_NOT_MATCHED;
    }

    public int getX() {
        return mX;
    }

    public int getY() {
        return mY;
    }

    public String getObjectName(){
        return mObjectName;
    }

    public int getState() {
        return mState;
    }

    ...

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(this.mX);
        dest.writeInt(this.mY);
        dest.writeString(this.mObjectName);
        dest.writeInt(this.mState);
    }

    protected CGameCard(Parcel in) {
        this.mX = in.readInt();
        this.mY = in.readInt();
        this.mObjectName = in.readString();
        this.mState = in.readInt();
    }

    public static final Creator<CGameCard> CREATOR = new Creator<CGameCard>() {
        @Override
        public CGameCard createFromParcel(Parcel source) {
            return new CGameCard(source);
        }

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

我想为这些对象创建一个二维可分割数组,以便将其存储在配置更改的共享首选项中。 这是由 parcelable android studio 插件生成的内容:

    public class GameCardArrArr implements Parcelable {
    private CGameCard[][] mArray;

    public GameCardArrArr(CGameCard[][] array) {
        mArray = array;
    }

    public CGameCard[][] getArray() {
        return mArray;
    }

    public void setArray(CGameCard[][] mArray) {
        this.mArray = mArray;
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeParcelable(this.mArray, flags);
    }

    protected GameCardArrArr(Parcel in) {
        this.mArray = in.readParcelable(CGameCard[][].class.getClassLoader());
    }

    public static final Creator<GameCardArrArr> CREATOR = new Creator<GameCardArrArr>() {
        @Override
        public GameCardArrArr createFromParcel(Parcel source) {
            return new GameCardArrArr(source);
        }

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

编译器不接受,因为显然它不正确。

创建此 parcelable 的正确方法是什么?

首先,我会警告在传输 parcelables 时有 1 MB 的非常严格的大小限制。如果你做一个像这样的双数组,那么我可以想象它会 非常 很容易达到那个限制并导致崩溃。

总之,回答问题。您完全可以在 Parcel 对象中放入任何您想要的东西,以重新创建该对象。所以在这种情况下,你需要知道数组的二维,然后根据这些维度填充数组即可。您所要做的就是确保您编写它们的方式与您阅读它们的方式完全相同(所有 parcelables 都是如此)。

一种方法是先写出双数组中有多少个数组,然后写出每个数组。

所以在这种情况下,您的 writeToParcel 将是这样的:

void writeToParcel(Parcel dest, int flags) {
   int numOfArrays = mArray.length;
   dest.writeInt(numOfArrays); // save number of arrays
   for (int i = 0; i < numOfArrays; i++) {
      dest.writeParcelableArray(mArray[i], flags);
   }
}

所以现在你知道第一个 int 是双数组中卡片数组的数量。

GameCardArrArr(Parcel in) {
   int numberOfArrays = in.readInt();
   mArray = new CGameCard[numberOfArays][];
   for (int i = 0; i < numberOfArrays; i++) {
      mArray[i] = (CGameCard[]) in.readParcelabeArray(CGameCard.class.getClassLoader());
   }
}

感谢 Deev 的回答,我朝着正确的方向前进。但是我在这一行遇到了强制转换异常:

(CGameCard[]) in.readParcelabeArray(CGameCard.class.getClassLoader());

为了解决这个问题,我最后使用了 writeTypedArraycreateTypedArray 方法。 下面是我的工作代码:

进入writeToParcel方法GameCardArrArr class:

public void writeToParcel(Parcel dest, int flags) {
   int numOfArrays = mArray.length;
   dest.writeInt(numOfArrays); // save number of arrays
   for (int i = 0; i < numOfArrays; i++) {
       dest.writeTypedArray(mArray[i] , flags);
   }
}

Parcel 作为参数进入 GameCardArrArr 构造函数:

protected GameCardArrArr(Parcel in) {
    int numberOfArrays = in.readInt();
    mArray = new CGameCard[numberOfArrays][];
    for (int i = 0; i < numberOfArrays; i++) {
        mArray[i] = in.createTypedArray(CGameCard.CREATOR);
    }
}

希望对您有所帮助