简体   繁体   中英

How to make an inner class Parcelable

I need to know how to make an inner class Parcelable so that objects of its type can be passed via AIDL to a remote service. I cannot find any information on this.

Here is example code of what I am trying to accomplish, but it doesn't compile because the CREATOR in the Bar class cannot be static (ie because it's in an inner class). I cannot make Bar a static inner class and I cannot move Bar outside of the Foo class (other dependencies within the system). I also need to know how I would reference the Bar class from within an AIDL file. Any help is greatly appreciated.

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>()
        {
            ...
        }
    }
}

I recently ran into the same problem and making the inner class static worked in my situation.

I read up on why this would actually work and it makes more sense to me, so I thought I would share. An inner class is a class that is nested inside another class and has a reference to an instantiation of its containing class. Through that reference it can access the containing classes members as if it were the containing class itself. Therefore it is bound to an instance of the containing class and thus can't have static members (since they would not be bound to the containing class).

Declaring the nested class as static decouples it from an instance of the containing class, and therefore can have its own static variables (and whatever else a regular class can have). Of course it will not be able to access members of the containing class.

The answer is that an inner class can always be made into its own class. Whatever functionality the inner class need to access from the instance of the outter class or vise versa can always be done via an interface or public API. Try making Bar its own class. Whatever components of Foo Bar needs access to, provide by passing the instance of Foo into Bar and implement the appropriate API.

If your outer class keeps a reference to the inner class instances you could do it like this:

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];
         }
    }
}

Your Bar doesn't have to be Parcelable. You can just save Bar fields along with Foo fields and restore entire object in createFromParcel(Parcel) method.

Here's some code fore example:

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;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM