Как сделать внутренний класс Parcelable - PullRequest
8 голосов
/ 27 января 2012

Мне нужно знать, как сделать внутренний класс Parcelable таким образом, чтобы объекты его типа могли передаваться через AIDL удаленному сервису. Я не могу найти информацию по этому вопросу.

Вот пример кода того, что я пытаюсь выполнить, но он не компилируется, потому что CREATOR в классе Bar не может быть статическим (то есть потому, что он находится во внутреннем классе). Я не могу сделать Bar статическим внутренним классом и не могу переместить Bar за пределы класса Foo (другие зависимости внутри системы). Мне также нужно знать, как я буду ссылаться на класс Bar из файла AIDL. Любая помощь с благодарностью.

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

Ответы [ 4 ]

8 голосов
/ 14 января 2014

Недавно я столкнулся с той же проблемой, и статический внутренний класс работал в моей ситуации.

Я прочитал о том, почему это на самом деле работает, и это имеет для меня больше смысла, поэтому я решил поделиться. Внутренний класс - это класс, который вложен в другой класс и имеет ссылку на создание экземпляра его содержащего класса. Через эту ссылку он может получить доступ к содержащим классам членам, как если бы это был сам содержащий класс. Поэтому он связан с экземпляром содержащего класса и, следовательно, не может иметь статических членов (поскольку они не будут связаны с содержащим классом).

Объявление вложенного класса как статического развязывает его от экземпляра содержащего класса и, следовательно, может иметь свои собственные статические переменные (и все, что может иметь обычный класс). Конечно, он не сможет получить доступ к членам содержащего класса.

3 голосов
/ 27 января 2012

Ответ в том, что внутренний класс всегда можно превратить в его собственный класс.Независимо от того, к какой функциональности внутренний класс должен обращаться из экземпляра внешнего класса или наоборот, он всегда может быть выполнен через интерфейс или открытый API.Попробуйте сделать Бар своим собственным классом.К каким компонентам Foo Bar требуется доступ, предоставьте, передав экземпляр Foo в Bar, и реализуйте соответствующий API.

1 голос
/ 02 декабря 2012

Если ваш внешний класс хранит ссылку на экземпляры внутреннего класса, вы можете сделать это так:

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];
         }
    }
}
0 голосов
/ 07 сентября 2017

Ваш бар не должен быть подлежащим продаже. Вы можете просто сохранить поля 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;
        }
    }
}
...