我已经成功地为我的main Activity实现了onRetainNonConfigurationInstance(),以保存和恢复屏幕方向变化中的某些关键组件.

但是,当方向改变时,我的自定义视图似乎正在从头开始重新创建.这是有道理的,尽管在我的例子中这很不方便,因为所讨论的自定义视图是X/Y图,并且打印的点存储在自定义视图中.

有没有一种巧妙的方法可以为自定义视图实现类似于onRetainNonConfigurationInstance()的东西,或者我只需要在自定义视图中实现一些方法,这些方法允许我获取并设置它的"状态"?

推荐答案

您可以通过实现View#onSaveInstanceStateView#onRestoreInstanceState并扩展View.BaseSavedState类来实现这一点.

public class CustomView extends View {

  private int stateToSave;

  ...

  @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.stateToSave = this.stateToSave;

    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.stateToSave = ss.stateToSave;
  }

  static class SavedState extends BaseSavedState {
    int stateToSave;

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

    private SavedState(Parcel in) {
      super(in);
      this.stateToSave = in.readInt();
    }

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

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

工作在视图和视图的SavedState类之间拆分.你应该做SavedStateParcel人的所有读写工作.然后,您的View类可以执行提取状态成员的工作,并执行使类返回有效状态所需的工作.

Notes: View#onSavedInstanceState and View#onRestoreInstanceState are called automatically for you if View#getId returns a value >= 0. This happens when you give it an id in xml or call setId manually. Otherwise you have to call View#onSaveInstanceState and write the Parcelable returned to the parcel you get in Activity#onSaveInstanceState to save the state and subsequently read it and pass it to View#onRestoreInstanceState from Activity#onRestoreInstanceState.

另一个简单的例子是CompoundButton

Android相关问答推荐

Android Kotlin DSL Gradle找不到自定义存储库中的依赖项

Android配置设置. gradle不同应用风格

如何在Jetpack composeH中创建具有弯曲末端的六边形形状

NativeScript在`ns run android`上重复Kotlin类

如何从Android 12的来电中获取电话号码?

无法加载类';com.android.build.api.extension.AndroidComponentsExtension';

数据绑定在Android中等待填充值时显示未填充的值

如何在喷气背包中绕过集装箱

在 kotlin 协同 routine 中,如何将数据范围限定为请求路径(以 MDC 为例)?

Android:使用依赖项 ViewModelProviderFactory 初始化 ViewModel 的正确方法

如何仅同步 local_manifest.xml?

运行设备选项卡在 Android Studio 中自动打开

延时kotlin中时分秒的使用方法

在 Jetpack Compose 中清除列表时可组合不重组

为 AlertDialog 的消息文本设置自定义字体

是什么让 Android Studio 中的按钮变成紫色?加上新手的其他奇怪行为

在jetpack compose中将图像添加到脚手架顶部栏

在 Compose 中使用 DeepLink 会导致无法向后导航

可扩展性 Qt 5.15 Android

为什么使用 React Native 和 expo 创建的 APK 体积这么大?