【问题标题】:Parcelable and inheritance in AndroidAndroid 中的 Parcelable 和继承
【发布时间】:2011-05-02 06:25:06
【问题描述】:

我得到了一个 Parcelable 的实现,它为一个不涉及继承的单个类工作。当涉及到继承时,我很难找出实现接口的最佳方式。假设我得到了这个:

public abstract class A {
    private int a;
    protected A(int a) { this.a = a; }
}

public class B extends A {
    private int b;
    public B(int a, int b) { super(a); this.b = b; }
}

问题是,这是为 B 实现 Parcelable 接口的推荐方法(在 A 中?在它们两个中?如何?)

【问题讨论】:

  • 自从您打开此问题后,您是否找到了比这更好的解决方案?
  • 不,我认为我下面提出的解决方案相当简单,对我来说就像一个魅力。
  • 它是否适用于多态使用,例如具有 B 对象的 A 类型数组?
  • 不知道,试试看,然后在这里发布你的结果。

标签: java android design-patterns inheritance parcelable


【解决方案1】:

这是我最好的解决方案,我很高兴收到对此有想法的人的意见。

public abstract class A implements Parcelable {
    private int a;

    protected A(int a) {
        this.a = a;
    }

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

    protected A(Parcel in) {
        a = in.readInt();
    }
}

public class B extends A {
    private int b;

    public B(int a, int b) {
        super(a);
        this.b = b;
    }

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

        public B[] newArray(int size) {
            return new B[size];
        }
    };

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel out, int flags) {
        super.writeToParcel(out, flags);
        out.writeInt(b);
    }

    private B(Parcel in) {
        super(in);
        b = in.readInt();
    }
}

【讨论】:

  • 我们是否也需要在 B 类(子类)中实现 Parcelable?
  • @jsmith 不,我没有,如果你试试就告诉我。
  • @CheokYanCheng 不,因为A实现了它,这意味着B也实现了(无需在B声明中重复implements Parcelable
  • @MarvinLabs 有什么理由不需要提供 describeContents 实现吗? (我可以理解为什么 A 不提供 CREATOR,因为它是抽象的并且无法创建自身的实例)另外,我可以知道测试一切是否正确的正确方法吗?能够从 Bundle 中保存和检索足够吗?
  • 我试图通过 AIDL 传递 A,但它不起作用。 B 丢失。解决方法是将对象放在一个 Bundle 中并通过 AIDL 传递该包。您只需要确保在另一端使用正确的类加载器。
【解决方案2】:

这是我的变种。我认为这很好,因为它非常清楚地显示了虚拟读写方法之间的对称性。

旁注:我认为 Google 在设计 Parcelable 界面方面做得非常糟糕。

public abstract class A implements Parcelable {
    private int a;

    protected A(int a) {
        this.a = a;
    }

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

    public void readFromParcel(Parcel in) {
        a = in.readInt();
    }
}

public class B extends A {
    private int b;

    public B(int a, int b) {
        super(a);
        this.b = b;
    }

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

        public B[] newArray(int size) {
            return new B[size];
        }
    };

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel out, int flags) {
        super.writeToParcel(out, flags);
        out.writeInt(b);
    }

    public void readFromParcel(Parcel in) {
        super(in);
        b = in.readInt();
    }
}

【讨论】:

  • 如果你想打包一个列表会发生什么?
  • createFromParcel()中,不应该是B b = new B(in);而不是B b = new B(); b(in);吗?后者(您当前的代码)不会编译,因为 b(in) 不是有效的方法或构造函数调用。
【解决方案3】:

这是 A 类在现实世界中的实现,因为 B 类可能有多个具有除 int 之外的不同类型的对象

它使用反射来获取类型。然后使用排序函数对字段进行排序,以便读取和写入以相同的顺序发生。

https://github.com/awadalaa/Android-Global-Parcelable

【讨论】:

  • Parcelable 被引入以避免使用反射 API,因为它很慢。您所做的是将慢速反射 API 与现代 Parcelable 解决方案相结合。这不是它的使用方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
  • 1970-01-01
  • 2012-03-08
  • 2014-09-07
  • 2017-09-05
相关资源
最近更新 更多