如何使用Android DataBinding库在屏幕方向更改时保留用户输入?

5
我现在开始一个新的安卓项目。在上一个项目中尝试过MVP架构后,这一次我想使用MVVM和Data Binding。但是,在配置更改(如屏幕方向)时,我无法正确理解DataBinding。
所有关于DataBinding和MVVM的示例都有同样的问题:当我在EditText中输入内容并旋转屏幕后,EditText会变为空白。 只要我的布局中有以下类似代码,我就不能保持视图(例如EditText)在屏幕旋转后恢复其状态。
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="vm"
            type="com.example.app.TestViewModel" />
    </data>

    <EditText android:id="@+id/question"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@={vm.question}" 
        android:hint="Question" />

</layout>

我猜这是因为在活动的onCreate方法中每次分配一个新的视图模型实例。
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ActivityTestBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_test);
    binding.setVm(new TestViewModel());
}

你如何正确地处理这个问题?

我无法开发一个具有多个表单的应用程序,因为在屏幕方向变化时会忘记所有用户输入。


我有完全相同的问题...... 我尝试将Icicle包含在ViewModel中,但是那样你就必须包括 onSave... 这破坏了MVVM的整个优势。 - george_mx
2个回答

23

双向数据绑定实际上与自动视图状态恢复兼容,但为了使其工作,您需要在视图状态恢复之前应用绑定

默认情况下,数据绑定将延迟所有绑定直到下一次布局传递,这发生在视图状态已经被恢复之后。这意味着视图状态实际上将被恢复,但是绑定值将覆盖视图的当前值。

要立即应用绑定,请在视图状态恢复之前调用executePendingBindings(),例如在Activity.onCreate()中:

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ActivityTestBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_test);

    viewModel = new TestViewModel();
    binding.setVm(viewModel);
    binding.executePendingBindings();
}

这就是你需要做的全部内容。当然,视图需要具有android:id属性,以便它们的状态可以自动保存和恢复。

当视图状态被恢复时,还将分配恢复的值到使用双向绑定绑定的属性,因此您的ViewModel将反映已恢复的状态。


3

您需要通过重写活动类中的onSaveInstanceState()方法来保存视图模型的状态,并在onCreate()方法中进行恢复。

private static final String QUESTION = "testViewModel.question";
private TestViewModel mTestViewModel;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ActivityTestBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_test);

    mTestViewModel = new TestViewModel();
    // Check whether we're recreating a previously destroyed instance
    if (savedInstanceState != null) {
         // restore view model state
         String questionVal = savedInstanceState.getString(QUESTION, "");
         mTestViewModel.setQuestion(questionVal);
    }
    binding.setVm(mTestViewModel);
}

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save current view model state
    savedInstanceState.putString(QUESTION, mTestViewModel.getQuestion());

    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}

有关“保存-恢复”技术的更多信息,您可以在此文档部分阅读。


这是一个失去的功能,因为在Android中,否则会自动恢复视图的值等,在方向改变时,但是使用MVVM,我们必须手动恢复状态。 - AmeyaB

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