I have an activity which displays two fragments:
- When activity is created, it displays
Fragment1. - When the user presses the button on
Fragment1, it displaysFragment2, adding to backstack.
Fragments are straightforward. Fragment1 contains CheckBox and EditText. Fragment2 contains simple TextView. Also I call setRetainInstance(true) in fragment’s onCreate(...) method.
Problem: Fragment1 loses its state if Fragment2 is displayed and device is rotated twice. However, everything works as expected if device is rotate only once.
Steps to reproduce:
- Launch application.
- Check
CheckBoxand type some text intoEditText - Press
Buttonto launchFragment2 - Rotate device
- Rotate device once again
- Press
Backbutton on your device (orESCon Emulator) to return back toFragment1
Fragment1 lost its state (checkbox is unchecked and EditText is empty).
However, if you return back to Fragment1 after step#4 – Fragment1 keeps its state as expected.
Where is the problem? All code is below, including layouts.
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent" />
fragment1.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<CheckBox
android:id="@+id/checkBox1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CheckBox" />
<EditText
android:id="@+id/editText1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</EditText>
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start Fragment2" />
</LinearLayout>
fragment2.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Fragment #2" />
</LinearLayout>
FragmentTestActivity.java:
package fragmenttest.example.com;
import android.app.Activity;
import android.app.FragmentManager;
import android.os.Bundle;
public class FragmentTestActivity extends Activity implements FragmentListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
FragmentManager fm = getFragmentManager();
if (fm.findFragmentByTag(Fragment1.TAG) == null) {
fm.beginTransaction().replace(R.id.placeholder, new Fragment1(), Fragment1.TAG).commit();
}
}
@Override
public void onButtonClick() {
FragmentManager fm = getFragmentManager();
if (fm.findFragmentByTag(Fragment2.TAG) == null) {
fm.beginTransaction().replace(R.id.placeholder, new Fragment2(), Fragment2.TAG).addToBackStack(Fragment2.TAG).commit();
}
}
}
Fragment1.java:
package fragmenttest.example.com;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
public class Fragment1 extends Fragment {
public static final String TAG = Fragment1.class.getName();
private FragmentListener mListener;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment1, container, false);
Button button = (Button) root.findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mListener.onButtonClick();
}
});
return root;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mListener = (FragmentListener) activity;
}
}
Fragment2.java:
package fragmenttest.example.com;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class Fragment2 extends Fragment {
public static final String TAG = Fragment2.class.getName();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment2, container, false);
return root;
}
}
FragmentListener.java:
package fragmenttest.example.com;
public interface FragmentListener {
public void onButtonClick();
}
It may be because onCreate isn’t called when restoring the fragment.
See:http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)