В этом уроке рассмотрим вложенный граф, global action и deep link.
Полный список уроков курса:
- Урок 1. Lifecycle
- Урок 2. LiveData
- Урок 3. LiveData. Дополнительные возможности
- Урок 4. ViewModel
- Урок 5. Room. Основы
- Урок 6. Room. Entity
- Урок 7. Room. Insert, Update, Delete, Transaction
- Урок 8. Room. Query
- Урок 9. Room. RxJava
- Урок 10. Room. Запрос из нескольких таблиц. Relation
- Урок 11. Room. Type converter
- Урок 12. Room. Миграция версий базы данных
- Урок 13. Room. Тестирование
- Урок 14. Paging Library. Основы
- Урок 15. Paging Library. PagedList и DataSource. Placeholders.
- Урок 16. Paging Library. LivePagedListBuilder. BoundaryCallback.
- Урок 17. Paging Library. Виды DataSource
- Урок 18. Android Data Binding. Основы
- Урок 19. Android Data Binding. Код в layout. Доступ к View
- Урок 20. Android Data Binding. Обработка событий
- Урок 21. Android Data Binding. Observable поля. Двусторонний биндинг.
- Урок 22. Android Data Binding. Adapter. Conversion.
- Урок 23. Android Data Binding. Использование с include, ViewStub и RecyclerView.
- Урок 24. Navigation Architecture Component. Введение
- Урок 25. Navigation. Передача данных. Type-safe аргументы.
- Урок 26. Navigation. Параметры навигации
- Урок 27. Navigation. NavigationUI.
- Урок 28. Navigation. Вложенный граф. Global Action. Deep Link.
- Урок 29. WorkManager. Введение
- Урок 30. WorkManager. Критерии запуска задачи.
- Урок 31. WorkManager. Последовательность выполнения задач.
- Урок 32. WorkManager. Передача и получение данных
- Урок 33. Практика. О чем это будет.
- Урок 34. Практика. TodoApp. Список задач.
- Урок 35. Практика. TodoApp. Просмотр задачи
Вложенный граф - это граф, который может быть создан внутри другого графа.
Для этого надо выделить все destination, который вы хотите переместить во вложенный граф, нажать правой кнопкой и выбрать Move to Nested Graph > New Graph
Созданный граф может уехать в другой конец экрана. Надеюсь это будет исправлено, а пока используем удобную кнопку для настройки зума, чтобы найти наш новый граф и вернуть его на место.
Вложенный граф - это обычный destination в основном графе. Так же, как фрагмент или Activity. И у этого destination есть параметры.
Все здесь нам уже знакомо.
Двойным кликом можно открыть граф
Вернуться обратно в основной граф можно нажав на Root в левой панели:
Я не нашел, как в дизайнере трансформировать вложенный граф обратно в фрагменты в основном графе. Проще всего это сделать руками через XML.
Так выглядит граф с вложенным графом
<?xml version="1.0" encoding="utf-8"?> <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" app:startDestination="@id/fragment1"> <fragment android:id="@+id/fragment1" android:name="ru.startandroid.navigation.Fragment1" android:label="@string/fragment_1_title" tools:layout="@layout/fragment1" /> <navigation android:id="@+id/navigation2" app:startDestination="@id/fragment2"> <fragment android:id="@+id/fragment2" android:name="ru.startandroid.navigation.Fragment2" android:label="@string/fragment_2_title" tools:layout="@layout/fragment2" /> <fragment android:id="@+id/fragment3" android:name="ru.startandroid.navigation.Fragment3" android:label="@string/fragment_3_title" tools:layout="@layout/fragment3" /> </navigation> </navigation>
Т.е. вложенный граф - это тег navigation внутри основного navigation тега.
Удаляем этот вложенный тег и фрагменты оказываются обратно в основном графе.
<?xml version="1.0" encoding="utf-8"?> <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" app:startDestination="@id/fragment1"> <fragment android:id="@+id/fragment1" android:name="ru.startandroid.navigation.Fragment1" android:label="@string/fragment_1_title" tools:layout="@layout/fragment1"/> <fragment android:id="@+id/fragment2" android:name="ru.startandroid.navigation.Fragment2" android:label="@string/fragment_2_title" tools:layout="@layout/fragment2" /> <fragment android:id="@+id/fragment3" android:name="ru.startandroid.navigation.Fragment3" android:label="@string/fragment_3_title" tools:layout="@layout/fragment3" /> </navigation>
Навигация
Допустим, мы создали вложенный граф с фрагментами fragment2 и fragment3. А в основном графе остался fragment1.
Теперь, находясь в fragment1 мы не можем сделать так:
navController.navigate(R.id.fragment2);
Будет ошибка: navigation destination ru.startandroid.navigation:id/fragment2 is unknown to this NavController.
Так происходит, потому что fragment1 находится в основном графе. И когда мы из fragment1 пытаемся куда то перейти, то контроллер пытается найти цель (fragment2) в этом же графе, но там ее нет. Зато там есть вложенный граф с ID = navigation2. Вот его и надо открывать:
navController.navigate(R.id.navigation2);
В результате контроллер найдет destination c ID = navigation2, увидит, что это граф, и откроет его стартовый destination, т.е. fragment2.
Т.е. из внешнего графа нельзя вызвать destination вложенного графа. А вот наоборот - можно.
Добавим, например, fragment4
Из любого destination во вложенном графе мы можем перейти к fragment4 обычным путем:
navController.navigate(R.id.fragment4);
В этом случае контроллер сначала будет искать цель (fragment4) в текущем графе (navigation2), а если не найдет, то продолжит поиски в родительском графе и там уже найдет.
Внутри вложенных графов также можно создавать вложенные графы .
Global Action
Обычно у Action есть destination-источник, откуда этот action может быть вызван, и destination-назначение, куда этот action ведет. Но можно сделать global action, у которого нет источника. И любой destination сможет вызвать этот action. Это удобно, если один и тот же destination вызывается из разных мест, но при этом используются одни и те же параметры.
global action создается так:
Он имеет те же атрибуты, что и обычный action
Вызывается он тоже, как обычный action
navController.navigate(R.id.action_global_fragment3);
Deep Link
Deep Link предназначен для открытия приложения сразу на определенном экране. С помощью Navigation Component мы можем присваивать такие ссылки необходимым destination.
Например для fragment3, мы присвоим ссылку: app://myapp/frag3
Далее, если у вас студия версии 3.2, то в манифесте в тег Activity, необходимо добавить тег nav-graph
<activity android:name=".MainActivity" android:label="MainActivity"> ... <nav-graph android:value="@navigation/main_graph" /> </activity>
И студия сама настроит Intent Filter.
Если же у вас студия более старой версии, то необходимо вручную настроить Intent Filter под этот deep link.
Проверить ссылку можно с помощью adb команды:
adb shell am start -a android.intent.action.VIEW -d "app://myapp/frag3"
При вызове этой команды будет открыто приложение, а в нем сразу fragment3.
В deep link ссылке можно использовать параметры. Например, если для фрагмента задана такая ссылка:
app://myapp/frag3/{id}
то после вызова ссылки
app://myapp/frag3/100
мы в открывшемся фрагменте можем получить id из аргументов.
String id = getArguments().getString("id");
Символ .* позволяет заменить часть ссылки
Т.е. если ссылка задана следующим образом:
app://myapp/frag3/.*/{id}
то фрагмент будет открыт при вызове ссылки:
app://myapp/frag3/test1/100
или
app://myapp/frag3/test1/test2/100
Присоединяйтесь к нам в Telegram:
- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance
- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня