Here's a simple android app I've created to demonstrate my problem:
public class OptionMenuTest extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("test", "create activity");
setContentView(R.layout.options_layout);
if(getFragmentManager().findFragmentByTag("frag") == null) {
getFragmentManager().beginTransaction().add(R.id.option_fragment_container, new OptionMenuFragment(), "frag").commit();
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
Log.d("test", "saving Activity state");
super.onSaveInstanceState(outState);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
Log.d("test", "create Activity options menu");
menu.add("activity");
return true;
}
}
Fragment:
public class OptionMenuFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("test", "create fragment");
setHasOptionsMenu(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
TextView tv = new TextView(getActivity());
tv.setText("Hello world");
Log.d("test", "create fragment view");
return tv;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.add("fragment");
Log.d("test", "create fragment options menu");
}
}
Layout is just a LinearLayout to dump the fragment into:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/option_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</LinearLayout>
Very simple right? When I run it I get the following output as expected:
06-12 15:42:51.415: D/test(957): create activity
06-12 15:42:51.446: D/test(957): create fragment
06-12 15:42:51.446: D/test(957): create fragment view
06-12 15:42:51.446: D/test(957): create Activity options menu
06-12 15:42:51.446: D/test(957): create fragment options menu
Now when I rotate the phone I get some strange behavior:
06-12 15:43:11.251: D/test(957): saving Activity state
06-12 15:43:11.290: D/test(957): create fragment
06-12 15:43:11.290: D/test(957): create activity
06-12 15:43:11.306: D/test(957): create fragment view
06-12 15:43:11.306: D/test(957): create Activity options menu
06-12 15:43:11.306: D/test(957): create fragment options menu
06-12 15:43:11.306: D/test(957): create Activity options menu
06-12 15:43:11.306: D/test(957): create fragment options menu
Why is the activity onCreateOptionMenu and fragment onCreateOptionsMenu called twice? If I remove the options menu from the fragment I get 1 call to the activity onCreateOptionsMenu as expected:
06-12 15:50:03.610: D/test(1076): create fragment
06-12 15:50:03.610: D/test(1076): create fragment view
06-12 15:50:03.813: D/test(1076): create Activity options menu
06-12 15:50:08.392: D/test(1076): saving Activity state // <-- rotate happens here
06-12 15:50:08.446: D/test(1076): create fragment
06-12 15:50:08.446: D/test(1076): create activity
06-12 15:50:08.462: D/test(1076): create fragment view
06-12 15:50:08.470: D/test(1076): create Activity options menu
I don't understand this and no one else seems to have encountered this problem. The real problem is that my SearchView is not able to recover it's state on config change (phone rotate) because the onCreateOptionMenu is being called twice. The first time it seems to have it's state but the second time it's cleared out and reset. I'm not able to figure out what I'm doing wrong.
Thanks in advance.
I think I found the answer to this problem.
Take a look a this:
https://stackoverflow.com/a/7225296/48468
The problem seems to be related to the fact that Android does not destroy the fragment when the activity is destroyed (when the device is rotated).
Basically I added :
setRetainInstance(true);
to my fragment constructor and the problem go solved.
Hope it helps!
@Gerardo Contijoch answer is misleading, except for one fact:
In your example both Activity
and Fragment
get destroyed upon rotation and created again.
That is why onCreateOptionsMenu()
is called twice. This is correct and expected behaviour.
By setRetainInstance(true)
you tell Android not to destroy the fragment. This may prove useful in case of UI-less fragment holding no Activity' context (useful for AsyncTasks coordination and some other service-like stuff).
In other cases fragment this potentially leads to memory leak, which you are to avoid.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With