getSupportFragmentManager().findFragmentByTag непредсказуемое поведение
Если я добавляю фрагменты в свою деятельность следующим образом:
fragment_tags = new ArrayList<String>();
fragment_tags.add("user_fragment");
fragment_tags.add("memorial_fragment");
UserFragment user = new UserFragment();
MemorialFragment memorial = new MemorialFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.content_frame, user, fragment_tags.get(0));
ft.add(R.id.content_frame, memorial, fragment_tags.get(1));
ft.commit();
и затем через некоторое время я пытаюсь получить эти фрагменты, как это:
List<Fragment> frg = getSupportFragmentManager().getFragments();
Fragment fragUser = getSupportFragmentManager().findFragmentByTag(
"user_fragment");
Fragment fragUserID = getSupportFragmentManager().findFragmentById(
R.id.user_fragment_id);
Log.d("MV", "fragments size:" + (frg == null ? " null" : frg.size()));
Log.d всегда будет возвращать размер 2, но fragUser иногда равен нулю, а иногда это фрагмент, который я помещаю в транзакцию.
Что более интересно, так это код:
try {
Log.d("MV", "0:" + frg.get(0).toString());
Log.d("MV", "1:" + frg.get(1).toString());
} catch (NullPointerException e) {
Log.d("MV", "null caught");
}
иногда будет работать для обоих фрагментов, а иногда только для первого, и если я сделаю что-то вроде этого:
if(frg.get(0) == fragUser)
иногда оно будет оцениваться как истинное, но не часто. Я не совсем понимаю это поведение, но мне нужно реализовать переключение между несколькими фрагментами, поэтому мне нужно получить ссылку на точный фрагмент. Кто-нибудь? Я пытаюсь решить это в течение 6 часов, и я действительно не понимаю, как это сделать. Спасибо
1 ответ
Поскольку этот вопрос был опубликован мной еще в 2013 году, набрал более 1000 просмотров, но до сих пор не получил никакого ответа, я постараюсь подвести итог тому, что я узнал за годы работы с фрагментами.
- Не используйте getSupportFragmentManager(). GetFragments() (подробнее об этом в getSupportFragmentManager(). GetFragments () показывает ошибку времени компиляции)
- FragmentManager предназначен для управления жизненным циклом фрагментов. Не пытайтесь помещать фрагменты в свои собственные списки или сохраняйте сильную ссылку на них
- Причина, почему
if(frg.get(0) == fragUser)
не работает последовательно, связан с пунктом 2. - FragmentManager управляет фрагментами, поэтому, когда он решает убить один и воссоздать его снова, ссылки не будут совпадать.
Теперь вопрос - как безопасно работать с фрагментами?
- Передайте данные фрагментам в комплекте, используя метод setArguments(), чтобы Android мог уничтожить и воссоздать фрагмент.
FragmentManager.findFragmentById(R.id.some_id)
найдет фрагмент, который прикреплен к представлению с идентификатором some_id. Весьма вероятно, что если у вас есть несколько фрагментов, добавленных в R.id.some_id,FragmentManager.findFragmentById(R.id.some_id)
будет давать разные результаты (но обычно это очень хороший способ узнать, какой фрагмент виден в данный момент, если вы также не скрываете / не отображаете свои фрагменты)- Понимать различные методы из API FragmentTransaction, особенно различия между
add
а такжеreplace
,hide
,detach
,remove
а такжеshow
, - Иногда что-то просто не работает (происходит сбой при одновременном запуске нескольких анимаций перехода между фрагментами), или ваше приложение не подходит для фрагментов. Вы можете прочитать больше о последнем в теперь классическом посте https://medium.com/square-corner-blog/advocating-against-android-fragments-81fd0b462c97