Получение ссылки на вложенный фрагмент из FragmentTabHost

В моем приложении я использую Activity, который содержит один Fragment с FragmentTabHost, и, следовательно, все его вкладки nested Fragments.

Внутри Activity, который содержит Fragment со своим nested Fragment, мы можем получить ссылку на присоединенный с помощью onAttachedFragment().

Но как получить ссылку на nested Fragment из FragmentTabHost?


person Alex Bonel    schedule 09.04.2013    source источник


Ответы (4)


Что ж, исследуя исходный код FragmentTabHost, я обнаружил, что когда он добавляет вкладку фрагмента, он назначает тег TabSpec вложенному Fragment.

Итак, чтобы получить ссылку на этот Fragment, мы должны вызвать

getChildFragmentManager().findFragmentByTag(tabSpecTag)

person Alex Bonel    schedule 09.04.2013
comment
не могли бы вы опубликовать код, где именно вы делаете сопоставление, потому что я всегда получаю NullPointerException по моей ссылке - person Ravi; 09.11.2013
comment
@Ravi, я добавил этот код в свой фрагмент метода onActivityCreated(), где я получаю ссылку на этот фрагмент - person DavyJonesUA; 21.07.2014
comment
Вы вызываете getChildFragmentManager() для какого объекта? - person Cozzamara; 03.07.2015
comment
Я называю это в родительском Fragment. - person Alex Bonel; 03.07.2015
comment
Если я назову это fragmentTabHost.addTab(fragmentTabHost.newTabSpec(TAG) .setIndicator(view), MyFragment.class, null);, то сразу после выполнения getSupportFragmentManager().findFragmentByTag(TAG); я получу ноль. Я делаю это в Activity, так как мне нужна ссылка на фрагмент. Не уверен, как заставить его работать. - person ono; 24.09.2015
comment
@ono Похоже, вы вызываете неправильный менеджер фрагментов, попробуйте getChildFragmentManager() вместо getSupportFragmentManager() - person Alex Bonel; 29.09.2015

Я пробовал это какое-то время, но мне возвращалось null из FragmentManager, потому что я пытался получить доступ к менеджеру в onCreateView() сразу после добавления.

Вот хорошее объяснение того, что произошло

Также важно отметить, что Fragment вкладки, которые еще не были выбраны, еще не существуют в FragmentManager, поэтому также будет возвращено null. Я обошел это, позвонив mTabHost.setCurrentTab(index) перед попыткой добраться до Fragment с помощью FragmentManager. Это не очень чисто, но работает.

person loadedion    schedule 09.04.2013
comment
Ну, я получаю ссылку на вложенный Fragment в onViewCreated() в начале жизненного цикла родительского Fragment, проверяя, является ли пакет savedInstanceState нулевым - в этом случае я знаю, что Fragment должно отображаться по умолчанию, и использовать определенный тег, в другом случае я получаю int значение из этого пакета, которое представляет отмеченную вкладку, которую я сохранил там ранее, и использую ее для приведения к определенному классу фрагмента. Также я назначаю ссылку на вложенную вкладку с помощью OnTabChangeListener, используя тег TabSpec, переданный методу onTabChanged(). - person Alex Bonel; 11.04.2013

Вышеупомянутые решения также работают, но у меня есть еще одно простое решение,

 @Override
public void onTabChanged(final String tabId) {

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {

            mFragment = getChildFragmentManager().findFragmentByTag("Tagname");
        }
    },1000);
}

Здесь вам нужно реализовать FragmentTabHost.onTabChangeListener. Мы сохранили вторую задержку при получении фрагмента из childFragmentManager.

Примечание. Вам нужно указать mFragment, какой фрагмент вы использовали.

person Nirav Shah    schedule 19.11.2014
comment
Одна вещь, которую я вижу как недостаток, заключается в том, что здесь вы делаете потенциальную утечку памяти, выделяя память для анонимного объекта Handler. После вызова он сохраняет ссылку на внешний класс около секунды. Поэтому, если вы прекратите свою деятельность сразу после смены вкладки, у вас все еще будет висячая ссылка на нее в памяти. Вам следует подумать дважды, если вы вызываете этот код внутри класса Activity. Более того, если пользователь решит возиться с вашими вкладками и пролистнет их в случайном порядке, вы заполните очередь сообщений Runnable, и их невозможно будет удалить из Handler. - person Alex Bonel; 20.11.2014
comment
Согласен с вами, но я хотел бы получить правильное место для вызова этого метода mFragment = getChildFragmentManager().findFragmentByTag(Tagname); ... Это код, в котором я нашел решение. Спасибо за ваш глубокий обзор :) - person Nirav Shah; 21.11.2014

Я нашел решение, которое мне нравится немного больше, потому что оно не связано с выполнением кода с задержкой (что всегда сомнительно, учитывая фрагментацию оборудования Android и разные скорости процессора).

В вашем методе onTabChanged(), прежде чем пытаться найти фрагмент, вызовите executePendingTransactions() в диспетчере фрагментов, связанном с вашим tabHost. Кажется, в исходном коде FragmentTabHost есть места, где они должны вызывать executePendingTransactions(), но не могут этого сделать.

Это работает каждый раз, когда вкладка изменяется с одним исключением... первая выбранная вкладка по-прежнему возвращает значение null... В моем конкретном случае я все равно смог обработать это исключение по-разному, добавив некоторый код в onResume.

Надеюсь это поможет.

person Justin    schedule 05.02.2015