В этом уроке рассмотрим как передавать данные при навигации.

 

 


Полный список уроков курса:


 

 

Чтобы при вызове destination передать данные, необходимо использовать Bundle. Для него оставили местечко в методе navigate

Bundle bundle = new Bundle();
bundle.putString("arg1", "value1");
bundle.putInt("arg2", 2);
navController.navigate(R.id.fragment2, bundle);

Создаем Bundle, наполняем аргументами и передаем в метод navigate вместе с ID destination (или action).


В фрагменте fragment2 метод getArguments вернет следующий Bundle:

Bundle[{arg1=value1, arg2=2}]

 

Соответственно получить данные можно стандартным путем:

String arg1Value = getArguments().getString("arg1");
Integer arg2Value = getArguments().getInt("arg2");

 

А если вызывали не фрагмент, а Activity, то так:

String arg1Value = getIntent().getStringExtra("arg1");
Integer arg2Value = getIntent().getIntExtra("arg2", 0);

 

 

 

Аргументы в графе

 

В графе мы можем для destination добавить аргументы и прописать им значения по умолчанию.

Секция Arguments. Указываем имя аргумента, тип и значение по умолчанию. Тип может быть string, integer и reference.

Если тип reference, то мы можем указать идентификатор какого-либо ресурса. В данном примере я указал dimen и string ресурсы. Они имеют следующие значения.

<dimen name="some_size">20dp</dimen>
<string name="app_name">Navigation</string>

 

Давайте проверим, как работают эти значения по умолчанию. Снова вызовем fragment2 и при этом не будем задавать никаких значений для аргументов, которые только что создали.

Bundle bundle = new Bundle();
bundle.putString("arg1", "value1");
bundle.putInt("arg2", 2);
navController.navigate(R.id.fragment2, bundle);

 

В результате getArguments в фрагменте выглядит так:

Bundle[{arg1=value1, arg2=2, arg3=defaultValue3, arg4=52, arg5=Navigation}]

Для аргументов arg3, arg4 и arg5 пришли дефолтные значения. Причем reference идентификаторы были конвертированы в соответствующие им значения. arg4 надо получать, как Int, а arg5 - как String.

 

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

Если для аргумента нет значения по умолчанию в графе и в коде ничего не было задано в Bundle, то в destination этот аргумент просто не придет.

 

 

 

Type-safe

Студия может сгенерировать нам классы и методы для удобной передачи аргументов. Для этого нам понадобится safeargs плагин.

 

В build.gradle файл проекта в секцию buildscript > dependencies необходимо добавить classpath

buildscript {
    repositories {
        google()
    }
    dependencies {
        classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0-alpha01"
    }
}

 

А в build.gradle модуля добавляем плагин safeargs

apply plugin: 'com.android.application'
apply plugin: 'androidx.navigation.safeargs'

android {
   //...
}

 

Для полноценного использования плагина необходимо использовать action.

Добавим action, который будет вести из fragment1 к fragment2 и укажем ID = actionToFragment2.

Обратите внимание, что action подтянул аргументы из destination в который он ведет, т.е. из fragment2. И мы можем указать для них значения по умолчанию.

Итак, у нас в графе есть три компонента, которые участвуют в навигации:
- destination, которому принадлежит (из которого выходит) action (ID = fragment1)
- action (ID = actionToFrgament2)
- destination, в который ведет action (ID = fragment2)

Для каждого из них будет сгенерирован свой класс. Если классы не генерируются, нажмите Ctrl+F9.

 

Отправитель

Для fragment1 будет сгенерирован класс Fragment1Directions. Т.е. в качестве имени взято ID и добавлено слово Directions. В этом классе будет метод actionToFragment2(), который даст нам action ActionToFragment2.

 

action

ActionToFragment2 - сгенерированный класс для action actionToFragment2. У этого класса есть методы, соответствующие аргументам этого action (см. скриншот выше). Т.е. для аргументов arg3, arg4 и arg5 будут созданы методы:

setArg3(String arg3)
setArg4(int arg4)
setArg5(int arg5)

и мы сможем их использовать, чтобы задавать значения аргументов. Под капотом там все также используется Bundle.

 

Код навигации будет выглядеть так:

Fragment1Directions.ActionToFragment2 action = Fragment1Directions.actionToFragment2();
action.setArg3("value3").setArg4(R.dimen.some_other_size).setArg5(R.string.hello_blank_fragment);
navController.navigate(action);

Получаем ActionToFragment2 из Fragment1Directions, задаем значения аргументов и передаем этот action в метод navigate.

 

Получатель 

Для получателя будет сгенерирован класс Fragment2Args. Т.е. для имени используется ID destination + суффикс Args.

У этого класса будут созданы методы для извлечения данных из bundle.

Статический метод, для создания Fragment2Args с передачей ему bundle.

public static Fragment2Args fromBundle(Bundle bundle)

 

И методы получения значения аргументов.

public String getArg3()
public int getArg4()
public int getArg5()



Код извлечения аргументов будет выглядеть так:

Fragment2Args fragment2Args = Fragment2Args.fromBundle(getArguments())
String arg3Value = fragment2Args.getArg3();
Integer arg4Value = fragment2Args.getArg4();
Integer arg5Value = fragment2Args.getArg5();

 

А если получатель - Activity, то код такой:

String arg3Value = SecondActivityArgs.fromBundle(getIntent().getExtras()).getArg3();

 

Эти сгенерированные классы очень просты, вы всегда можете открыть их и посмотреть код. В целом они являются оберткой над Bundle.


Присоединяйтесь к нам в Telegram:

- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование 

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

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




Language

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

 

Telegram канал



Android чат в Telegram



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



Страница в Facebook