如何创建一个内部类Parcelable

10

我需要知道如何使一个内部类Parcelable,以便可以通过AIDL将其类型的对象传递到远程服务。我找不到任何相关信息。

这是我尝试实现的示例代码,但它无法编译,因为Bar类中的CREATOR不能是静态的(即因为它在内部类中)。我不能将Bar设置为静态内部类,也不能将其移出Foo类(系统中有其他依赖项)。我还需要知道如何从AIDL文件中引用Bar类。非常感谢任何帮助。

public class Foo implements Parcelable
{
    private int a;

    public Foo()
    {
    }

    public Foo(Parcel source)
    {
        this.a = source.readInt();
    }

    public int describeContents()
    {
        return 0;
    }

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

    public static final Parcelable.Creator<Foo> CREATOR
    = new Parcelable.Creator<Foo>()
    {
        ...
    }

    public class Bar implements Parcelable
    {
        private int b;

        public Bar()
        {
        }

        public Bar(Parcel source)
        {
            this.b = source.readInt();
        }

        public int describeContents()
        {
            return 0;
        }

        public void writeToParcel(Parcel dest, int flags)
        {
            dest.writeInt(this.b);
        }

        public static final Parcelable.Creator<Bar> CREATOR
        = new Parcelable.Creator<Bar>()
        {
            ...
        }
    }
}

你可以查看http://stackoverflow.com/questions/35923039/android-implementing-parcelable-inner-class,这会对你有所帮助。 - chaitanya
看一下这个解决方案。这将帮助你 http://stackoverflow.com/questions/35923039/android-implementing-parcelable-inner-class - chaitanya
4个回答

8
我最近遇到了同样的问题,将内部类设为静态在我的情况下起作用。
我查阅了相关资料,现在我更加理解为什么这样做是可行的,所以我想分享一下。内部类是嵌套在另一个类中的类,并且具有对其包含类实例化的引用。通过该引用,它可以像包含类本身一样访问包含类成员。因此,它绑定到包含类的实例,因此不能具有静态成员(因为它们不会绑定到包含类)。
将嵌套类声明为静态可以使其与包含类的实例分离,因此可以拥有自己的静态变量(以及其他常规类可以拥有的内容)。当然,它将无法访问包含类的成员。

当使用嵌套的可包含类时,将内部可包含类声明为“static”对我很有用。 - Eido95

3
答案是内部类总是可以成为自己的类。无论内部类需要从外部类实例访问什么功能,或者反过来,都可以通过接口或公共API来实现。尝试将Bar变成自己的类。无论Bar需要访问Foo的哪些组件,都通过将Foo实例传递到Bar中并实现适当的API来提供。

谢谢您的回复。是的,那将是理想的解决方案。但是,我必须与一些jni代码进行接口(我没有C++重新编译),该代码期望一个Foo.Bar(如果得到一个Bar就会崩溃)。 - MichaelL

1
如果你的外部类保留了对内部类实例的引用,你可以像这样做:
public class OuterClass implements Parcelable
{
    private InnerClass reference;

    protected OuterClass( Parcel source )
    {
        this.reference = new InnerClass( source );
        // ...
    }

    @Override
    public void writeToParcel( Parcel destination, int flags )
    {
        reference.writeToParcel( destination, flags );
        // ...
    }

    public class InnerClass implements Parcelable
    {
        protected InnerClass( Parcel source )
        {
            // Read from your parcel.
        }

        @Override
        public void writeToParcel( Parcel destination, int flags )
        {
            // Write to your parcel.
        }
    }

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

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

1
你的Bar类不一定需要实现Parcelable接口。你可以将Bar类的字段和Foo类的字段一起保存,并在createFromParcel(Parcel)方法中还原整个对象。
以下是示例代码:
import android.os.Parcel;
import android.os.Parcelable;

public class Foo implements Parcelable {
    private int mFooData = 0;
    private Bar mBar;

    public Foo() {
    }

    protected Foo(Parcel in) {
        mFooData = in.readInt();

        // Reading Bar
        int barData = in.readInt();
        mBar = new Bar(barData);
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mFooData);

        // Writing Bar
        dest.writeInt(mBar.getBarData());
    }

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

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

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

    public class Bar {
        private int mBarData = 0;

        public Bar(int barData) {
            mBarData = barData;
        }

        public int getBarData() {
            return mBarData;
        }

        public void setBarData(int mBarData) {
            this.mBarData = mBarData;
        }
    }
}

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