Android在自定义视图中管理配置更改(状态)

时间:2011-08-24 20:43:00

标签: android

这是后续行动:Android local variable get's lost when using camera intent

正确的方法是处理此处显示的onSaveInstanceStateonRestoreInstanceState
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/widget/CompoundButton.java

这是我的代码:

static class SavedState extends BaseSavedState
    {
        private String requestedFileName;
        private UUID[] mImages = new UUID[4];

        SavedState(Parcelable superState)
        {
          super(superState);
        }

        private SavedState(Parcel in)
        {
          super(in);
        }

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

        //required field that makes Parcelables from a Parcel
        public static final Parcelable.Creator<SavedState> CREATOR =
            new Parcelable.Creator<SavedState>()
            {
              public SavedState createFromParcel(Parcel in)
              {
                return new SavedState(in);
              }
              public SavedState[] newArray(int size)
              {
                return new SavedState[size];
              }
        };

    }

    @Override
    public Parcelable onSaveInstanceState()
    {
        //begin boilerplate code that allows parent classes to save state
        Parcelable superState = super.onSaveInstanceState();

        SavedState ss = new SavedState(superState);
        //end

        ss.requestedFileName = this.requestedFileName;
        ss.mImages = this.mImages;

        return ss;
    }

    @Override
    public void onRestoreInstanceState(Parcelable state)
    {
        //begin boilerplate code so parent classes can restore state
        if(!(state instanceof SavedState))
        {
            super.onRestoreInstanceState(state);
            return;
        }

        SavedState ss = (SavedState)state;
        super.onRestoreInstanceState(ss.getSuperState());
        //end

        this.requestedFileName = ss.requestedFileName;
        this.mImages = ss.mImages;

        RestoreImageState();
    }

现在回答我的问题。此代码似乎正常工作,它处理所有状态更改没有问题。但是,如果你看 SavedState.writeToParcel SavedState.SavedState ,你会注意到我没有存储我的变量。我一定要吗?为什么?问题是我了解如何wrteToParcel和我的数据类型匹配。但是从复杂的类型中读出包裹并不是那么清楚。在我的测试中它没有被调用。

编辑:

这对于保存/撤退订单看起来是否正确?

private SavedState(Parcel in)
        {
          super(in);
          this.mName = in.readString();
          this.mIndex = in.readInt();
          this.mApplicableDamages = (String[])in.readValue(null);
          this.mSelectedDamages = (boolean[])in.readValue(null);                            
        }

        @Override
        public void writeToParcel(Parcel out, int flags)
        {
          super.writeToParcel(out, flags);
          out.writeString(this.mName);
          out.writeInt(this.mIndex);
          out.writeArray(this.mApplicableDamages);
          out.writeBooleanArray(this.mSelectedDamages);
        }

1 个答案:

答案 0 :(得分:1)

您必须在onSaveInstanceState()中保存这些变量,如果它们是您视图状态的一部分,则必须在onRestoreInstanceState()之后将其恢复,并且您不希望在重新创建父活动时丢失它们。

变量可能会丢失,因为当配置更改发生时,父活动将被销毁并重新创建新的活动对象。此新对象将接收先前保存的状态。如果你没有在状态中添加一些变量,那么就无法恢复。

关于向Parcel编写复杂类型并从中读取,您可以为复杂类型的某些部分实现Parcelable。或者,您可以将复杂类型分解为基元(parcelable)字段并逐个存储此字段。在您的情况下,UUID[]可以Parcel存储为Serializable,或者您可以将UUID[]转换为ParcelUuid[]并将此数组存储为parcelable数组。

关于SavedState实施的几句话。如果您不将其添加到SavedState,则Parcel中的字段将不会保存。因此,您必须在Parcel方法中写入SavedState.writeToParcel()。而且你需要在SavedState(Parcel)构造函数中读回它们。

static class SavedState extends BaseSavedState
{
    private String requestedFileName;
    private UUID[] mImages = new UUID[4];

    SavedState(Parcelable superState)
    {
        super(superState);
    }

    private SavedState(Parcel in)
    {
        super(in);
        requestedFileName = in.readString();
        mImages = (UUID[])in.readSerializable();
    }

    @Override
    public void writeToParcel(Parcel out, int flags)
    {
        super.writeToParcel(out, flags);
        out.writeString(requestedFileName);
        out.writeSerializable(mImages);
    }

    //required field that makes Parcelables from a Parcel
    public static final Parcelable.Creator<SavedState> CREATOR =
        new Parcelable.Creator<SavedState>()
        {
            public SavedState createFromParcel(Parcel in)
            {
                return new SavedState(in);
            }

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