使用Parcelable在Activity间传递高度嵌套的类

3
假设我想在一个 Intent 中存储一个自定义类型为 MyObject 的对象。实现此目的的方法是让 MyObject 实现 Parcelable 接口。如果 MyObject 的字段之一也是 Widget 类型的自定义对象,则显而易见的做法是让 Widget 也实现 Parcelable 接口。
问题在于,实现 Parcelable 接口时涉及大量样板代码。您可以通过不让 Widget 实现 Parcelable 接口,而只是提供一个带有 Parcel 参数的构造函数和一个名为 writeToParcel 的方法来解决这个问题。
public final class Widget {

    private final int a;
    private final String b;

    Widget(Parcel in) {
        a = in.readInt();
        b = in.readString();
    }

    void writeToParcel(Parcel out) {
        out.writeInt(a);
        out.writeString(b);
    }
}

您可以在Parcelable对象中添加一个Widget字段,如下所示:

public class MyObject implements Parcelable {

    private final int x;
    private final Widget w;

    MyObject(int x, Widget w) {
        this.x = x;
        this.w = w;
    }

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

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(x);
        w.writeToParcel(out);
    }

    public static final Parcelable.Creator<MyObject> CREATOR
            = new Parcelable.Creator<MyObject>() {
        @Override
        public MyObject createFromParcel(Parcel in) {
            return new MyObject(in.readInt(), new Widget(in));
        }
        @Override
        public MyObject[] newArray(int size) {
            return new MyObject[size];
        }
    };
}

这是一个可接受的方式吗?在一个项目中有许多自定义类,它们可以被写入和读取Parcel,但它们实际上没有实现Parcelable,这在android上是否考虑为非惯用方式?或者我使用Parcelable传递具有许多自定义类型字段的复杂对象(这些对象又具有许多自定义类型字段等等),这是否表明我首先不应该使用Parcelable

3个回答

2
我会选择Parceler: https://github.com/johncarl81/parceler Parceler是一个代码生成库,用于生成Android Parcelable基本源代码。您不再需要实现Parcelable接口、writeToParcel()或createFromParcel()或public static final CREATOR。您只需使用@Parcel注释一个POJO,Parceler将处理剩下的部分。
它非常易于使用。

0

如果你的类是JavaBeans,那么最好的解决方案就是接受的那个。如果不是,我发现你可以通过创建抽象类ParcelablePlusCreatorPlus来(稍微)减少实现Parcelable的痛苦。

ParcelablePlus

abstract class ParcelablePlus implements Parcelable {

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

CreatorPlus:

abstract class CreatorPlus<T extends Parcelable> implements Parcelable.Creator<T> {

    private final Class<T> clazz;

    CreatorPlus(Class<T> clazz) {
        this.clazz = clazz;
    }

    @Override
    @SuppressWarnings("unchecked")
    public final T[] newArray(int size) {
        // Safe as long as T is not a generic type.
        return (T[]) Array.newInstance(clazz, size);
    }
}

那么Widget类将变成:

public final class Widget extends ParcelablePlus {

    private final int a;
    private final String b;

    Widget(int a, String b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(a);
        out.writeString(b);
    }

    public static final Creator<Widget> CREATOR = new CreatorPlus<Widget>(Widget.class) {
        @Override
        public Widget createFromParcel(Parcel in) {
            return new Widget(in.readInt(), in.readString());
        }
    };
}

0

在Android中处理通过意图传递自定义对象时,建议使用Parcelable。没有“简单”的解决方法。由于您只处理一个自定义对象(Widget)的额外级别,我建议您也将Widget设置为Parcelable。您还可以查看此链接,了解为什么这比使用默认序列化更好。https://coderwall.com/p/vfbing/passing-objects-between-activities-in-android


不幸的是,这只是一个例子。我认为我的对象在现实中有4-5个层级。 - Paul Boddington
一个非正统的方法是,如果您有一个带有静态字段的类,您可以在活动之间切换时更新这些字段。例如,在启动Activity B的意图之前,Activity A将更新静态类中的MyObject字段,然后在Activity B中它将从静态类中读取该MyObject字段。这样,您甚至不需要考虑可包装性。 - Ian Osawaye
@PaulBoddington 看上面 - Ian Osawaye
我无法告诉你这种做法的诱惑力有多强。虽然我知道那样做非常不明智。 - Paul Boddington

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接