如何使用 Android DataBinding 库使用户输入的屏幕方向发生变化?

How to keep user inputs on screen orientation change with Android DataBinding library?

我正处于一个新 Android 项目的开始阶段。在我上一个项目中玩弄了 MVP 之后,这次我想用 Data Binding 实现 MVVM。

当涉及到屏幕方向更改等配置更改时,我无法正确理解 DataBinding。

那里的所有 DataBinding 样本(我在寻找 "android mvvm databinding" 时发现的所有样本)都有同样的问题:当我在 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());
}

你是如何正确处理的?

我无法开发具有多种表单的应用程序而忘记屏幕方向上的所有用户输入。

您需要通过重写 activity class 中的方法 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);
}

有关“save-restore”技术的更多信息,您可以在此阅读part of documentation

正确答案如下,详见:

ViewModels 应该比配置更改更有效。

使用新的架构组件,您可以轻松实现:

public class TestViewModel extends ViewModel{
    ...
}

然后在你的 Activity#onCreate(...):

public class MainActivity extends LifecycleActivity {

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

        ViewModelProvider provider = ViewModelProviders.of(this);
        binding.setVm(provider.get(TestViewModel.class));
    }
}

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

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

要立即应用绑定,请在恢复视图状态之前调用 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 将反映恢复的状态。