В этом уроке рассмотрим вложенный граф, global action и deep link.

 

Вложенный граф - это граф, который может быть создан внутри другого графа.

Для этого надо выделить все 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, Kotlin, RxJava, Dagger, Тестирование 

- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

- тут можно посмотреть, над какими уроками я сейчас работаю, и о чем будут следующие уроки 




Language

Социальные сети

 

Telegram канал



Android чат в Telegram



Группа ВКонтакте



Страница в Facebook