Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

After screen rotation, findFragmentById() returns a fragment, even if there's no such ID inside the layout

I have one layout in two orientations - 1 landscape and 1 portrait.

/layout-land/main.xml has two fragments:

  • <fragment android:id="@+id/fragment1" .. />
  • <fragment android:id="@+id/fragment2" .. />

/layout/main.xml has only one fragment:

  • <fragment android:id="@+id/fragment1" .. />

Here's the MainActivity.java:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    firstFragment = (FirstFragment) getFragmentManager().findFragmentById(R.id.fragment1);
    secondFragment = (SecondFragment) getFragmentManager().findFragmentById(R.id.fragment2);
}

Next, I start the MainActivity.java in landscape mode. In this case,

  • Both firstFragment and secondFragment refers to the fragments in the layout layout-land/main.xml

Then I rotate the screen to portrait mode, and the layout file layout/main.xml should be loaded. In this case,

  • firstFragment refers to the R.id.fragment1
  • secondFragment referes to a non-existant fragment. Accessing any elements inside this throws a NullPointerException. (To be more precise, secondFragment is not null here)

How this secondFragment is initialized when there's no fragment defined inside the layout?


Edit: Reason found on Android Developer Documentation at http://developer.android.com/training/basics/fragments/creating.html:

When a configuration change causes the activity hosting these fragments to restart, its new instance may use a different layout that doesn't include the same fragments as the previous layout. In this case all of the previous fragments will still be instantiated and running in the new instance. However, any that are no longer associated with a tag in the view hierarchy will not have their content view created and will return false from isInLayout(). (The code here also shows how you can determine if a fragment placed in a container is no longer running in a layout with that container and avoid creating its view hierarchy in that case.)

like image 557
Vishnu Haridas Avatar asked Oct 23 '13 06:10

Vishnu Haridas


People also ask

What happens if activity with retained fragment is rotated?

Fragments — Scenario 3: Activity with retained Fragment is rotated. The fragment is not destroyed nor created after the rotation because the same fragment instance is used after the activity is recreated.

How to put Fragment in activity?

You can add your fragment to the activity's view hierarchy either by defining the fragment in your activity's layout file or by defining a fragment container in your activity's layout file and then programmatically adding the fragment from within your activity.

What is the function of Fragment manager?

FragmentManager is the class responsible for performing actions on your app's fragments, such as adding, removing, or replacing them, and adding them to the back stack.

What is Fragment back stack in Android?

If you add one Fragment into the back stack, when you press the android device back menu, you can find the Fragment that is saved in the back stack popup. Until all the saved Fragments in the back stack popup, then the activity will exit.


2 Answers

You can check like below : I assume that you have Fragment1 class for the fragment you get by findFragmentById

Fragment1 frg1 =getFragmentManager().findFragmentById(R.id.FrgDetalleEvento);
boolean hayDetalle = ( frg1!= null && frg1.isInLayout());

It solved the same problem with me, hope it helpful for every of you

like image 165
Thành Trung Bùi Avatar answered Sep 26 '22 02:09

Thành Trung Bùi


maybe it's too late, but I leave it for future programmers with this problem, I had a similar problem and solved it this way.

Logic: Check the screen orientation, and call findViewById(R.id.fragment2) only if the screen is on landscape mode. Otherwise start a new intent to the other screen

Non working code;

@Override
public void onEventoSeleccionado(Evento e) {

    boolean hayDetalle = (getFragmentManager().findFragmentById(R.id.FrgDetalleEvento) != null);

            if(hayDetalle) {
                SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy hh:mm",Locale.ENGLISH);
                Log.i("EOLog", "Hay Detalle");
                ((DetalleEventoFragment)getFragmentManager().findFragmentById(R.id.FrgDetalleEvento)).mostrarDetalle(Long.toString(e.getId()),formatter.format(e.getFecha()));
            }
            else {
                Log.i("EOLog", "No hay detalle");           
                Intent i = new Intent(this,DetalleEventoActivity.class);                                        
                Bundle b = new Bundle();
                b.putLong("IDEV", e.getId());           
                b.putLong("FECHA", e.getFecha());           
                i.putExtras(b);
                startActivity(i);
            }

}

Working code:

@Override
public void onEventoSeleccionado(Evento e) {

      int orientation = getResources().getConfiguration().orientation;

            if(orientation == Configuration.ORIENTATION_LANDSCAPE) {
                SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy hh:mm",Locale.ENGLISH);
                Log.i("EOLog", "Hay Detalle");
                ((DetalleEventoFragment)getFragmentManager().findFragmentById(R.id.FrgDetalleEvento)).mostrarDetalle(Long.toString(e.getId()),formatter.format(e.getFecha()));
            }
            else if(orientation == Configuration.ORIENTATION_PORTRAIT) {
                Log.i("EOLog", "No hay detalle");           
                Intent i = new Intent(this,DetalleEventoActivity.class);                                        
                Bundle b = new Bundle();
                b.putLong("IDEV", e.getId());           
                b.putLong("FECHA", e.getFecha());           
                i.putExtras(b);
                startActivity(i);
            }else
            {
                Log.i("EOLog", "Dispositivo erroneo");
            }

}

I hope that is helpful

like image 45
Gabriel Nuñez Avatar answered Sep 27 '22 02:09

Gabriel Nuñez