Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I'm at the very beginning of a new Android project. After playing around with MVP in my last project, I want to implement MVVM with Data Binding this time.

I have a problem understanding DataBinding correctly when it comes to configuration changes like screen orientation change.

All DataBinding samples out there (all I have found when looking for "android mvvm databinding") have the same problem: When I enter something in an EditText and rotate the screen, the EditText is empty afterwards.

As soon as I have something like the following in my layout, I can't get the views (EditText in this case) to restore their state after screen rotation change.

<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>

I guess this is because of assigning a new view model instance in the activities onCreate method every time.

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

How do you handle that correctly?

I can't develop an app with several forms that forget all user inputs at screen orientation.

like image 762
maschin Avatar asked Feb 12 '17 16:02

maschin


People also ask

How do I stop Android from restarting activity when changing orientations?

If you want the activity to not restart during screen orientation change, you can use the below AndroidManifest. xml. Please note the activity android:configChanges=”orientation|screenSize” attribute. This attribute makes the activity not restart when change screen orientation.

How do I manage different orientations in Android?

If you want to manually handle orientation changes in your app you must declare the "orientation" , "screenSize" , and "screenLayout" values in the android:configChanges attributes. You can declare multiple configuration values in the attribute by separating them with a pipe | character.


2 Answers

Two-way data binding is actually compatible with automatic view state restoration, but for it to work you need to apply the binding before the view state is restored.

By default, data binding defers all bindings until the next layout pass, which occurs after the view state has been restored. This means the view state will actually be restored, but then the binding value(s) will overwrite the current values of the views.

To apply binding immediately, call executePendingBindings() before the view state is restored, for example in 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();
}

And that's all you need to do. Of course, the views need to have an android:id attribute in order for their state to be saved and restored automatically.

When the view state is restored, the restored values will also be assigned to the properties bound using two-way binding so your ViewModel will reflect the restored state.

like image 110
BladeCoder Avatar answered Nov 10 '22 01:11

BladeCoder


You need to save state of your view model by overriding of method onSaveInstanceState()in your activity class and restore it in onCreate() method.

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);
}

More information about "save-restore" technology you can read at this part of documentation

like image 41
Sergey Bubenshchikov Avatar answered Nov 10 '22 01:11

Sergey Bubenshchikov