После поворота экрана findFragmentById () возвращает фрагмент, даже если в макете нет такого идентификатора

У меня есть один макет в двух направлениях – 1 пейзаж и 1 портрет.

/layout-land/main.xml имеет два фрагмента:

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

/layout/main.xml имеет только один фрагмент:

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

Вот 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); } 

Затем я запускаю MainActivity.java в ландшафтном режиме. В этом случае,

  • И firstFragment и secondFragment относятся к фрагментам в макете layout-land/main.xml

Затем я поворачиваю экран в портретный режим и должен быть загружен макет файла layout/main.xml . В этом случае,

  • firstFragment относится к R.id.fragment1
  • secondFragment ссылается на несуществующий фрагмент. Доступ к любым элементам внутри этого алгоритма вызывает исключение NullPointerException. (Чтобы быть более точным, secondFragment здесь не равен null )

Как этот secondFragment инициализируется, когда внутри макета нет фрагмента?


Изменить: причина, найденная в документации для разработчиков Android на http://developer.android.com/training/basics/fragments/creating.html :

Когда изменение конфигурации вызывает перезапуск активности этих фрагментов, в новом экземпляре может использоваться другой макет, который не включает те же фрагменты, что и предыдущий макет. В этом случае все предыдущие фрагменты все равно будут созданы и запущены в новом экземпляре. Тем не менее, любые, которые больше не связаны с тегом в иерархии представления, не будут иметь созданного представления содержимого и вернут false из isInLayout (). (В этом коде также показано, как вы можете определить, больше ли работает фрагмент, размещенный в контейнере в макете с этим контейнером, и не создавайте в этом случае свою иерархию представлений).

Может быть, уже слишком поздно, но я оставляю это для будущих программистов с этой проблемой, у меня была аналогичная проблема и решил ее таким образом.

Логика. Проверьте ориентацию экрана и вызовите findViewById(R.id.fragment2) только если экран находится в режиме ландшафта. В противном случае начните новое намерение на другом экране

Нерабочий код;

 @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); } } 

Рабочий код:

 @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"); } } 

Я надеюсь, что это полезно

Вы можете проверить, как показано ниже: Я предполагаю, что у вас есть класс Fragment1 для фрагмента, который вы получаете с помощью findFragmentById

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

Он решил ту же проблему со мной, надеюсь, что это поможет каждому из вас

Перекрестно проверите setContentView () вашего класса активности.

Я думаю, что это должно быть setContentView (R.layout.main);

Intereting Posts
Android Drag and Drop для TextView, вызывающий исключение В чем разница между / system / app и / data / app? Как решить эту проблему зависимости от проекта Android? Как создать массив массивов с данными курсора в Android FATAL EXCEPTION: главная java.lang.UnsatisfiedLinkError в библиотеке Android Studio Xamarin.Forms Фотосъемка с камерой показывает неправильную ориентацию и сбой на задней кнопке Кнопка «Обратно» в «Реагировать родной», «Навигатор» на Android Проверить приложения Android Wear на телефоне? Android Studio: «Выполнение не выполнено для задачи»: app: mergeDebugResources «если проект создан на диске C: Android: как получить пользовательские фотографии в Instagram? Медиа-проигрыватель, вызываемый в состоянии 0, ошибка (-38,0) Как использовать Spinner в Recyclerview? Двойная проверка блокировки в Android Класс не найден с загрузчиком загрузчика; Нет доступной трассировки стека Android – циклическая часть кода каждые 5 секунд