The android activity provides a method to save/retrieve instance state data. Please read the article Android Save Retrieve Activity Instance State Example to learn more. The fragment also provides a method for you to save/retrieve related instance state data. This article will show you an example of how to save/retrieve instance state data in android Fragment.
1. How To Save / Retrieve Fragment Instance Data.
- In a Fragment, there are UI view objects and instance variables. For the UI view objects which has id, android OS will save their view instance state data automatically. You do not need to care.
- But for those Fragment instance variables, you need to save the value in the Bundle in onSaveInstanceState(Bundle outState) method. And retrieve those saved values from the Bundle in the onViewStateRestored(@Nullable Bundle savedInstanceState) method.
2. Fragment Save / Retrieve Instance Data Example.
- In this example, when changing the screen orientation from vertical to horizontal, the activity will be destroyed and recreated. Because the Fragment belongs to the activity, so the Fragment will also be destroyed and recreated.
- So in the below example, we log some text in all the fragment create and destroy methods. We also log in onSaveInstanceState(Bundle outState) method and onViewStateRestored(@Nullable Bundle savedInstanceState) method.
- The example started with a vertical screen.
- Click the turn orientation button to make the device a horizontal screen.
- Then you can see the Fragment life cycle method ( onCreate, onDestroy, etc ) invocation output log data in the Android Logcat monitor.
3. Example Source Code.
- activity_fragment_instance_state.xml: This is the main activity layout XML file.
<FrameLayout android:id="@+id/fragment_instance_state_frame_layout" android:layout_width="match_parent" android:layout_height="match_parent" />
- fragment_instance_state.xml: This is the Fragment layout XML file.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Input user email in below text box." android:textSize="20dp"/> <EditText android:id="@+id/fragment_instance_state_user_email_edit_box" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
- FragmentInstanceStateActivity.java: This is the main activity java file.
package com.dev2qa.example.fragment.instancestate; import android.os.Bundle; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.support.v7.app.AppCompatActivity; import android.util.Log; import com.dev2qa.example.R; import com.dev2qa.example.util.ActivityManagerUtil; import com.dev2qa.example.util.FragmentUtil; public class FragmentInstanceStateActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fragment_instance_state); setTitle("dev2qa.com - Fragment Instance State Example."); boolean addNewFragment = true; // If turn the screen orientation then the savedInstanceState is not null. // In this condition, do not need to add new fragment again. if(savedInstanceState!=null) { addNewFragment = false; } // Print out all activity in current task. ActivityManagerUtil.printCurrentTaskActivityList(getApplicationContext(), FragmentUtil.TAG_NAME_FRAGMENT); // Print out all fragment in current activity. FragmentUtil.printActivityFragmentList(getSupportFragmentManager()); if(addNewFragment) { Log.d(FragmentUtil.TAG_NAME_FRAGMENT, "Start to create a new fragment."); FragmentManager fragmentManager = this.getSupportFragmentManager(); FragmentInstanceState fragmentInstanceState = new FragmentInstanceState(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.add(R.id.fragment_instance_state_frame_layout, fragmentInstanceState, "Fragment Instance State"); fragmentTransaction.commit(); }else { Log.d(FragmentUtil.TAG_NAME_FRAGMENT, "Use exist fragment."); } } }
- FragmentInstanceState.java: This is the Fragment java file.
package com.dev2qa.example.fragment.instancestate; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.EditText; import com.dev2qa.example.R; import com.dev2qa.example.util.FragmentUtil; public class FragmentInstanceState extends Fragment { public static final String USER_EMAIL_KEY = "UserEmail"; private String userEmail = ""; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View retView = inflater.inflate(R.layout.fragment_instance_state, container, false); this.logDebugInfo("Fragment onCreateView method is called."); return retView; } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.logDebugInfo("Fragment onCreate method is called."); } @Override public void onDestroy() { super.onDestroy(); this.logDebugInfo("Fragment onDestroy method is called."); } @Override public void onDestroyView() { super.onDestroyView(); this.logDebugInfo("Fragment onDestroyView method is called."); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); // Get user input email from the edit text box. EditText userEmailInputBox = getActivity().findViewById(R.id.fragment_instance_state_user_email_edit_box); userEmail = userEmailInputBox.getText().toString(); if(outState!=null) { // Save user email instance variable value in bundle. outState.putString(this.USER_EMAIL_KEY, userEmail); this.logDebugInfo("Fragment onSaveInstanceState method is called.Save user input email " + userEmail); } } @Override public void onViewStateRestored(@Nullable Bundle savedInstanceState) { super.onViewStateRestored(savedInstanceState); if(savedInstanceState!=null) { // Retrieve the user email value from bundle. userEmail = savedInstanceState.getString(this.USER_EMAIL_KEY); // Do not need below code, because android os will automatically save and restore view objects value that has id attribute. // EditText userEmailInputBox = getActivity().findViewById(R.id.fragment_instance_state_user_email_edit_box); //userEmailInputBox.setText(userEmail); // Log the retrieved user email value. this.logDebugInfo("Fragment onViewStateRestored method is called.Retrieved user input email is " + userEmail); } } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); } private void logDebugInfo(String message) { Log.d(FragmentUtil.TAG_NAME_FRAGMENT, message); } }
- ActivityManagerUtil printCurrentTaskActivityList() method.: This is the util class method which print all activity list in current task.
// Print all activity info in current task back stack. public static void printCurrentTaskActivityList(Context context, String tagName) { ActivityManager activityManager = (ActivityManager) context.getSystemService( context.ACTIVITY_SERVICE ); List<ActivityManager.AppTask> appTaskList = activityManager.getAppTasks(); if(appTaskList!=null) { int size = appTaskList.size(); for(int i=0;i<size;i++) { ActivityManager.AppTask appTask = appTaskList.get(i); ActivityManager.RecentTaskInfo recentTaskInfo = appTask.getTaskInfo(); int taskId = recentTaskInfo.persistentId; int activityNumber = recentTaskInfo.numActivities; ComponentName origActivity = recentTaskInfo.origActivity; ComponentName baseActivity = recentTaskInfo.baseActivity; ComponentName topActivity = recentTaskInfo.topActivity; Log.d(tagName, "Task Id : " + taskId); Log.d(tagName, "Activity Number : " + activityNumber); if(origActivity!=null) { Log.d(tagName, "Original Activity : " + origActivity.toString()); } if(baseActivity!=null) { Log.d(tagName, "Base Activity : " + baseActivity.toString()); } if(topActivity!=null) { Log.d(tagName, "Top Activity : " + topActivity.toString()); } Log.d(tagName, "************************************************"); } } }
- FragmentUtil printActivityFragmentList() method: Util class method which print all fragment tag name in current activity.
// Print fragment manager managed fragment in debug log. public static void printActivityFragmentList(FragmentManager fragmentManager) { // Get all Fragment list. List<Fragment> fragmentList = fragmentManager.getFragments(); if(fragmentList!=null) { int size = fragmentList.size(); for(int i=0;i<size;i++) { Fragment fragment = fragmentList.get(i); if(fragment!=null) { String fragmentTag = fragment.getTag(); Log.d(TAG_NAME_FRAGMENT, fragmentTag); } } Log.d(TAG_NAME_FRAGMENT, "***********************************"); } }