It may look difficult to deal with the configuration changes and save the instance in Android but it is not. There are few scenarios in which the Activity gets destroyed and needs to be recreated and also the data need to be restored again and for this, the instance is always saved before destroying the activity. There are both types techniques in which Android automatically manages the data or you can do it manually. But it is recommended that you should manage the data manually. So that there will not be any issues or losses.
Let us see how to save data for configuration change while using data binding.
Suppose we are creating a login page. Consider the below-given class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
public class LoginActivityData implements Parcelable { private static final String TAG = "LoginActivityData"; private String username = ""; private String password = ""; public LoginActivityData() { } protected LoginActivityData(Parcel in) { username = in.readString(); password = in.readString(); } public static final Creator<LoginActivityData> CREATOR = new Creator<LoginActivityData>() { @Override public LoginActivityData createFromParcel(Parcel in) { return new LoginActivityData(in); } @Override public LoginActivityData[] newArray(int size) { return new LoginActivityData[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(username); dest.writeString(password); } // And getters and setters } |
The above Model contains two variables username and password and it also implements Parcelable because to save and retrieve the Object from memory. Although the edit texts automatically save the values all you need to do is give them an id. It is must for them to save the data.
This Model class will be used to save the values of username and password in the XML file of the activity. Below is the example of the activity_login.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="data" type="com.webkul.magento2.mobikulpos.models.login.LoginActivityData" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.design.widget.TextInputLayout android:id="@+id/username_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/spacing_tiny" app:error="@{data.usernameErrorMsg}"> <android.support.design.widget.TextInputEditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/login_username" android:inputType="text" android:maxLines="1" android:text="@={data.username}" android:textColor="@color/colorLoginActivityText" /> </android.support.design.widget.TextInputLayout> <android.support.design.widget.TextInputLayout android:id="@+id/password_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/spacing_generic" app:error="@{data.passwordErrorMsg}" app:passwordToggleEnabled="true" app:passwordToggleTint="@color/colorLoginActivityText"> <android.support.design.widget.TextInputEditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/login_password" android:inputType="textPassword" android:maxLines="1" android:text="@={data.password}" android:textColor="@color/colorLoginActivityText" /> </android.support.design.widget.TextInputLayout> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="end" android:text="@string/login_sign_in" /> </LinearLayout> </layout> |
We are using a two-way data binding in the above example so any changes in the edit text fields will be automatically updated to the model Object.
Now we have both the XML and the model class linked let us see how the object is assigned inside the Main Activity. Below is the example of the Main Activity class.
1 2 3 4 5 6 7 8 9 10 11 |
public class LoginActivity extends BaseActivity { public ActivityLoginBinding mLoginBinding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mLoginBinding = DataBindingUtil.setContentView(this, R.layout.activity_login); mLoginBinding.setData(new LoginActivityData()); } } |
In the above code segment, you can see that we have assigned our model class to the Class binding object. But in this case, Whenever the configurations are changed then everytime a new object is being initialized to it. So the data will not be saved and we will get the blank fields again.
To get the data first we need to save the instance and then after the configuration change, we need to add the data from the savedInstanceState. Below is the example of saving the instance.
1 2 3 4 5 |
@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putParcelable("loginPageData", mLoginBinding.getData()); } |
this will save the model object and when the activity is created again then it will be passed to the onCreate function and there you will check that if the savedInstanceState is not null then get the object from it and assign to the XML. Example of the above theory is given below.
1 2 3 4 5 6 7 8 9 10 11 |
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mLoginBinding = DataBindingUtil.setContentView(this, R.layout.activity_login); if (savedInstanceState == null) { mLoginBinding.setData(new LoginActivityData()); } else { mLoginBinding.setData((LoginActivityData) savedInstanceState .getParcelable("loginPageData")); }; } |
That’s all!