Android Fragment created a double orientation change

My snippet is created twice, although activity only adds the snippet once to the content. This happens when I rotate the screen. In addition, every time the onCreateView fragment is called, it has lost all this state of the variable.

public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (savedInstanceState == null) { // Checking for recreation getSupportFragmentManager().beginTransaction() .add(R.id.container, new AppPanelFragment()) .commit(); } } } 

onCreate in activity checks for null savedInstanceState, and only if null will add a fragment, so I can not understand why the fragment should be created twice? Putting a breakpoint in this condition when they tell me that it is ever called once, so the activity should not add a fragment several times. However, the onCreateView of the fragment is still called every time the orientation changes.

  public class AppPanelFragment extends Fragment { private TextView appNameText; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // This method called several times View rootView = inflater.inflate(R.layout.fragment_app_panel, container, false); // 2nd call on this method, appNameText is null, why? appNameText = (TextView) rootView.findViewById(R.id.app_name); appNameText.text = "My new App"; return view; } 

I managed to save the variable state using setRetainInstance (true), but is this a real solution? I would expect the fragment to not be created only when the orientation changes.

+5
source share
4 answers

Fragment life cycle is very similar to Activity . By default, yes, they will be recreated during configuration changes, as Activity does. This is the expected behavior. Even with setRetainInstance(true) (which I would say with extreme caution if it contains a user interface), your View will be destroyed and recreated, but in this case your Fragment instance will not be destroyed - just View .

+3
source

In android, when the orientation of the phone changes, the action is destroyed and recreated. Now I believe that I fixed your problem, you can use the fragment manager to check if the fragment exists in the background stack, and then it does not create it.

 public void onCreated(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (savedInstanceState == null) { mFragmentManager = getSupportFragmentManager(); AppPanelFragment fragment = (AppPanelFragment)mFragmentManager.findFragmentById(R.id.fagment_id); if(fragment == null) { //do your fragment creation } } } 

PS I have not tested this, but it should work as soon as you provide the correct fragment identifier in the findFragmentById method.

+4
source

As already mentioned, when the orientation changes, the activity is destroyed and recreated. In addition, Fragments (any) is recreated by the system.

To restore your application to its previous state, onSaveInstanceState () is called before the action is destroyed.

Thus, you can save some information in the onSaveInstanceState () method for activity, and then restore your application in the same state when the orientation changes.

NOTE. You do not need to create fragments when changing orientation, because fragments are recreated.

Example from http://www.mynewsfeed.x10.mx/articles/index.php?id=15 :

 public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if ( savedInstanceState == null ){ //Initialize fragments Fragment example_fragment = new ExampleFragment(); FragmentManager manager = getFragmentManager(); FragmentTransaction transaction = manager.beginTransaction(); transaction.add(R.id.container, example_fragment, "Example"); } else{ //control comes to this block only on orientation change. int postion = savedInstanceState.getInt("position"); //You can retrieve any piece of data you've saved through onSaveInstanceState() //finding fragments on orientation change Fragment example_fragment = manager.findFragmentByTag("Example"); //update the fragment so that the application retains its state example_fragment.setPosition(position); //This method is just an example } } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt("position", position); //add any information you'd like to save and restore on orientation change. } } 
0
source

I know it's a bit late to answer, but using "Reply to the Code", you can do the following:

If a fragment exists in the backstack, we drop it and delete it to add it back (an exception is thrown if it is added back without deleting it, if it already exists).

The fragment variable is a member variable of the class.

This method will be called in the onCreate Activity method:

  if (savedInstanceState == null) { FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); if (fragmentManager.findFragmentById(getFragmentActivityLayoutContainerId()) == null) { fragment = getNewFragmentInstance(); } else { fragment = fragmentManager.findFragmentById(getFragmentActivityLayoutContainerId()); fragmentTransaction.remove(fragment); fragmentManager.popBackStack(); fragmentTransaction.commit(); fragmentTransaction = fragmentManager.beginTransaction(); } fragmentTransaction.add(getFragmentActivityLayoutContainerId(), fragment); fragmentTransaction.commit(); } 

The following code will be called in the fragment itself.

This is a small example of code that you could implement in your snippet to understand how it works. DummyTV is a simple text view in the center of the fragment, which receives the text in accordance with the orientation (and for this we need a counter).

 private TextView dummyTV; private static int counter = 0; @Override protected int getFragmentLayoutId() { return R.layout.fragment_alerts_view; } @Override protected void saveReferences(View view) { dummyTV = (TextView) view.findViewById(R.id.fragment_alerts_view_dummy_tv); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { if (savedInstanceState != null) { dummyTV.setText(savedInstanceState.getString("dummy_string")); } else { dummyTV.setText("flip me!"); } dummyTV.append(" | " + String.valueOf(counter)); } @Override public void onSaveInstanceState(Bundle outState) { outState.putString("dummy_string", counter++ % 2 == 0 ? "landscape" : "portrait"); } 
0
source

Source: https://habr.com/ru/post/1215796/


All Articles