JetPack Navigation: как получить текущий Fragment

sashatinkoff
О разработке для Android
2 min readMay 25, 2022

Компонент Navigation помогает разработчикам разгрести непонятный мусор, связанный с кучей вызовов разных экранов из разных мест. Уже достаточно давно я написал небольшой хендлер Router для открытия Activity и проброски каких-то параметров внутри. Выглядело это, например, вот так

Любой вызов Activity дергал один и тот же метод внутри самой Activity. И это было достаточно удобно — вместо судорожного поиска по проекту, где же я вызвал startActivity(intent), я просто открывал нужную мне Activity и открывал все использования метода open.

С фрагментами все было не так просто. Да, я работал по схожей схеме

Но у меня не было общего класса типа FragmentRouter, и открывал я их с помощью fragmentTransaction, что было порой не очень удобно (что связано было например с Fragment.hide() и обработкой показа действительно текущего фрагмента, а не где-то спрятанного). Поэтому к компоненту JetPack Navigation я присматривался с очень большим интересом.

Раскрою свою мысль про обработку фрагментов чуть дальше.

Мне необходимо отслеживать изменения на открытый Fragment (впрочем, как и на закрытый), причем неважно кто является Fragment Host — Activity или какой-то другой фрагмент. Для этого какое-то время назад я написал небольшой классик FragmentConnector, который

а). Отправлял изменения о текущем фрагменте в вышестоящий хост (onResume / onPause)
б). Сохранял текущий фрагмент в хосте, чтобы его можно было отслеживать в любой удобный момент.

Таким образом иерархия Activity — Fragment у меня была довольно простая — Activity со стеком фрагментов, каждый из которых мог хранить в свою очередь свой стек фрагментов… и так далее.

Компонент Navigation немного сломал эту структуру. Там есть условная Activity, в ней есть NavHostFragment (который, если я не ошибаюсь, сам является фрагментом), в нем уже хранятся конкретно отображаемые фрагменты, в которых может быть свой NavHostFragment… и так далее

Смотрим как все немного схлапывается

Итак, далее я покажу измененные классы с примерами использования и объяснения как это работает

FragmentConnector

Суть крайне проста — соответственные методы вызываются в нужных местах базового фрагмента (главный предок всех ваших фрагментов)

Использование FragmentConnector в базовом фрагменте

Тут тоже все просто — в методах onResume, onPause и onHiddenChanged дергаем метод fragmentConnector. Ключевое отличие от не-Navigation находится в строчке

?: (parentFragment as? NavHostFragment)?.parentFragment as? FragmentConnector

Просто углубляемся на уровень ниже вместе с NavHostFragment, как я говорил выше.

Использование FragmentConnector в базовой Activity

Получение изменений о текущем фрагменте в Activity / Fragment

Бонус: получение ParentFragment

Если у нас фрагмент вызывается внутри другого фрагмента, то получить его через parentFragment c Navigation Component не получится. Используем такой способ

--

--

sashatinkoff
О разработке для Android

Пишу о разном с матом ем булку с маком никогда не бегал с автоматом