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 просмотров, но до сих пор не получил никакого ответа, я постараюсь подвести итог тому, что я узнал за годы работы с фрагментами.

  1. Не используйте getSupportFragmentManager(). GetFragments() (подробнее об этом в getSupportFragmentManager(). GetFragments () показывает ошибку времени компиляции)
  2. FragmentManager предназначен для управления жизненным циклом фрагментов. Не пытайтесь помещать фрагменты в свои собственные списки или сохраняйте сильную ссылку на них
  3. Причина, почему if(frg.get(0) == fragUser) не работает последовательно, связан с пунктом 2. - FragmentManager управляет фрагментами, поэтому, когда он решает убить один и воссоздать его снова, ссылки не будут совпадать.

Теперь вопрос - как безопасно работать с фрагментами?

  1. Передайте данные фрагментам в комплекте, используя метод setArguments(), чтобы Android мог уничтожить и воссоздать фрагмент.
  2. FragmentManager.findFragmentById(R.id.some_id) найдет фрагмент, который прикреплен к представлению с идентификатором some_id. Весьма вероятно, что если у вас есть несколько фрагментов, добавленных в R.id.some_id, FragmentManager.findFragmentById(R.id.some_id) будет давать разные результаты (но обычно это очень хороший способ узнать, какой фрагмент виден в данный момент, если вы также не скрываете / не отображаете свои фрагменты)
  3. Понимать различные методы из API FragmentTransaction, особенно различия между add а также replace, hide, detach, remove а также show,
  4. Иногда что-то просто не работает (происходит сбой при одновременном запуске нескольких анимаций перехода между фрагментами), или ваше приложение не подходит для фрагментов. Вы можете прочитать больше о последнем в теперь классическом посте https://medium.com/square-corner-blog/advocating-against-android-fragments-81fd0b462c97
Другие вопросы по тегам