Android jetpack navigation example

Using The Navigation Architecture Component in Android Jetpack (Kotlin) — Now updated to 1.0.0

Android’s answer to Storyboards in iOS

Table of Contents

Note: The GitHub codebase provided at the end of the article has now been updated to use Navigation 1.0.0. The diff commit for the same can be found here. The article in process of being updated to reflect the changes.

Introduction

A ndroid application development has taken a huge stride over the last few years. I started programming Android applications back in the days when writing the entire code in Activities was considered the **right** way of doing things. Since then, we have had Fragments come along, then came the idea of MVP/MVVM/MVI architectures, Reactive programming, Event Bus, Clean Architecture etc.

Google itself has decided to promote the Model-View-ViewModel approach to write applications in and has advocated it as part of their with Android Architecture Components framework which was further expanded into Android Jetpack during Google I/O 2018. Among the concepts introduced include ViewModel, LiveData, Room Database, WorkManager and Navigation. This article explains the last.

FYI : If you would like to get a good understanding of how Android Jetpack and Architecture Components work, here is a project called Sunflower currently under active development by Google and written in Kotlin that I would highly recommend.

Find the Github repo of an expanded sample app I created using the steps mentioned below

prasannajeet/android-navigation-example

How to use Android Navigation Architecture Component using Kotlin — prasannajeet/android-navigation-example

The core aspect of the Navigation Component lies in the application’s navigation graph. To understand what a navigation graph is we have to understand the concept of destinations. As per Google:

A destination is any place you can navigate to in your app. While destinations are usually Fragments representing specific screens, the Navigation Architecture Component supports other destination types:

  • Activities
  • Navigation graphs and subgraphs — when the destination is a graph or subgraph, you navigate to the starting destination of that graph or subgraph
  • Custom destination types

A set of destinations comprise your application’s navigation graph. In addition to destinations, a navigation graph has connections between destinations called actions.

Below image shows you the destinations in the sample app I ended up creating for myself. We will be creating a much simpler 2 fragment navigation graph in this tutorial

Enough talk. Lets see some code!

Setup

You need to have Android Studio 3.2 RC or above in order to work with any Android Jetpack components including Navigation ( download ). Also, for the purposes of this tutorial, knowledge of Kotlin is a must.

Create a new Android project, add a blank activity and let the gradle build finish

Add the following dependencies to your existing app/build.gradle file and perform a gradle sync. This should go in your dependencies<> block

Additionally, in order to support passing of values between the views involved in a navigation we would need to add the typesafe gradle plugin.

Add the navigation-safe-args-gradle-plugin in the project level build.gradle’s dependencies<> tag. The file should look something like this in its entirety.

Then in the app/build.gradle we have to add the following gradle plugin before the android<> block

For implementing Navigation, Android has introduced a new resource type called Navigation. Right click on the res directory and choose New -> Android resource file. Choose a title for the file and select Navigation from the Resource type dropdown. It should look something like this:

Читайте также:  Main xml для android

Once you have created the navigation xml file it will look something like this

If you haven’t already, go to File — Settings (Android Studio — Preferences in Mac) and click on Experimental on the left menu. Select Enable Navigation Editor on the right.

In you navigation graph xml file go to Design view and click on the New Destination icon and it should show something like this.

We will create two fragments here by clicking on the Create Blank Destination button. MainFragment and DestinationFragment. Once you have created both the fragments here your navigation xml file will look like this

And your design view should look something like this

The home icon on mainFragment signifies that its the s tarting point of your navigation. This usually is the fragment/activity that shows first when you launch the app.

In the next section, we will setup navigation from mainFragment to destinationFragment and pass a String value between them

Adding Action

In order for the framework to understand which destination it needs to go to from the source you have to specify an action. You will have to add the action tag inside your source/home fragment from where the navigation is to be performed.

Adding Arguments

Let’s say you are passing a name from your MainFragment into DestinationFragment and in the latter you show a message “Welcome $name”. I order to get the name from the source to the destination we need to pass it as an argument. You may add multiple such arguments.

Setting an Argument type in turns results in invoking that Fragment using the value passes as a Bundle argument. We will see how in the next section.

  1. android:name— The identifier for the argument
  2. app:argType— What datatype it is. Currently it supports inferred, integer, string, reference
  3. android:defaultValue (optional) — A default value that the recieving fragment will get in case the source fragment does not pass any value

With that done, your navigation XML file will now look like this.

And thus the navigation is setup, the framework knows what is the source, the destination and what data is to be passed along during navigation. Now let’s go and create a simple UI and stitch it all up with some Kotlin code

Creating The XML Layouts

We will create a very basic UI wherein we have an EditText and a Button in the MainFragment where we enter our name. Upon button click, we pass the name from MainFragment to DestinationFragment to be shown as “Welcome $name”.

Below is how my layouts look, feel free to copy it over to your project

And finally the Activity layout where will add the MainFragment

Some Kotlin Code To Get It All Working

Step 1: MainActivity

Add the MainFragment to the MainActivity in the onCreate() function. We will use NavHostFragment.create() to get our NavHostFragment which we then pass onto the FragmentTransaction to invoke the Fragment

setPrimaryNavigationFragment function is added to set up the backstack navigation of the Fragment notifying MainFragment as the host.

Step 2: MainFragment

In the MainFragment, we need to perform the action on the button click to navigate to DetailFragment taking along with it the name that’s entered in the EditText.

In the onViewCreated method of the Fragment, we get the action object that we added in the navigation XML under tag.

In this action we will add the name that’s entered in our EditText. This value will then be passed into the DestinationFragment as an argument

Finally, we invoke the NavController to perform the navigation

I have added input validation alongwith the above code and my MainFragment looks something like this at the end of the step

Step 3: DestinationFragment

In the DestinationFragment we will need to retrieve the argument passed and set it as the text in the TextView we have placed in the layout

We will get the arguments for the class navigated to by using the Args.from() function. For Example, in this case we get the name that was passed from MainFragment in this fashion.

Here nameToShow is the argument name that we had set in navigation XML file.

The final DestinationFragment class looks like this:

Conclusion

And that’s it! Once everything is set up, just run the app in the emulator and you would see the Navigation Framework work its magic for yourself.

Читайте также:  Get current orientation android

Like the article? Well slap on those claps.

Источник

Урок 12. Навигация в приложении. Начало работы с Navigation Architecture Component

В этом уроке на практике познакомимся с библиотекой Navigation Architecture Component , которая позволяет пользователям перемещаться между различными частями контента в вашем приложении. Компонент навигации входит в набор компонентов Android Jetpack и помогает реализовать навигацию, от простых нажатий кнопок до более сложных шаблонов, таких как панели приложений (appbars) и панель навигации (navigation drawer). Компонент навигации также обеспечивает согласованное и предсказуемое взаимодействие с пользователем, придерживаясь установленного набора принципов, о которых мы говорили на прошлом уроке.

Введение

Navigation Architecture Component упрощает осуществление навигации, а также помогает визуализировать navigation flow вашего приложения. Библиотека предоставляет ряд преимуществ, в том числе:

  • Автоматическая обработка транзакций фрагментов
  • Корректная обработка кнопок «Вверх» и «Назад» по умолчанию
  • Поведение по умолчанию для анимации и переходов
  • Deep linking как first class operation
  • Реализация шаблонов навигации пользовательского интерфейса (таких как navigation drawer и bottom navigation) с небольшой дополнительной работой
  • Безопасность типов при передаче информации во время навигации
  • Инструменты Android Studio для визуализации и редактирования navigation flow приложения

В этом уроке нам понадобится среда разработки Android Studio версии 3.3 или выше.

Мы будем использовать готовый проект, в котором уже есть необходимые активити или фрагменты. Нам нужно настроить навигацию в приложении, используя Navigation Architecture Component.

Скачайте стартовый проект по ссылке

Обзор компонента навигации

Компонент навигации состоит из трех ключевых частей:

  • Navigation graph: ресурс XML, который содержит всю связанную с навигацией информацию в одном централизованном месте. Это включает в себя все отдельные области содержимого в вашем приложении, называемые destinations (пункты назначения), а также возможные пути, которые пользователь может пройти через ваше приложение.
  • NavHost: Пустой контейнер, который отображает пункты назначения из вашего графика навигации. Компонент Navigation содержит реализацию NavHost по умолчанию — NavHostFragment, которая отображает фрагменты — места назначения.
  • NavController: Объект, который управляет навигацией приложения в NavHost. NavController управляет перемещениями контента мест назначения в NavHost , в процессе перемещения пользователей по приложению.

Мы используем объект NavController, сообщая ему путь в ресурсе Navigation Graph. Затем объекту NavController будет показан соответствующий пункт назначения в NavHostFragment.

Давайте посмотрим, как это выглядит на практике, начиная с нового ресурса Navigation Graph.

Destinations

Компонент навигации представляет концепцию Destinations — пункта назначения . Пункт назначения — это любое место, в котором вы можете перемещаться в приложении, обычно это фрагмент или активити. Они поддерживаются «из коробки», но вы также можете создавать свои собственные типы назначения, если это необходимо.

Navigation Graph представляет собой новый тип ресурса , который определяет все возможные пути, доступные пользователю в приложении. Он показывает визуально все пункты назначения, которые могут быть достигнуты из данного пункта назначения. Редактор навигации Android Studio отображает Navigation Graph наглядно.

Редактор навигации

  1. Откройтеres/navigation/mobile_navigation.xml
  2. Перейдите в режим «Дизайн»:

Navigation Graph показывает доступные пункты назначения. Стрелки между пунктами назначения называются actions (действия). Больше мы поговорим о них позже.

  1. Нажмите на пункт назначения, чтобы увидеть его атрибуты.
  2. Нажмите на любое действие, представленное стрелкой, чтобы увидеть его атрибуты.

Анатомия навигационного XML-файла

Все изменения, которые вы делаете в графическом редакторе навигации, изменяют базовый XML-файл, подобно тому, как редактор макетов изменяет XML-макет.

Перейдите на вкладку « Текст »:

Источник

Когда вы начинаете создавать приложение, в котором хотя бы несколько экранов, всегда встает вопрос — как лучше реализовать навигацию. Вопрос становится интереснее и сложнее, когда вы собираетесь делать многомодульное приложение. Примерно полтора года назад я рассказывал как можно реализовать навигацию c помощью Jetpack в многомодульном проекте. И вот спустя время, я наткнулся на свою реализацию и понял, что можно на том же Jetpack летать по модулям проще: без магии и DI.

Архитектура проекта

Чтобы покрыть основные кейсы я покажу как реализовать навигацию на многомодульном проекте такой структуры:

Типичная архитектура Android проекта: feature-модули c реализацией экранов зависят от shared-модулей с общей логикой. И app модуль, который зависит от feature и shared.

Сейчас довольно популярен подход Single Activity, поэтому в моем примере будет всего одна Activity с глобальным хостом, в котором будут переключаться фрагменты

Подготовка

От модуля shared:navigation зависят почти все модули проекта не просто так. В этом модуле реализована функция расширения фрагмента для реализации переходов.

У функции есть параметры:

actionId — id действия графа навигации

hostId — id хоста графа навигации. Если не будет передан, то будет использован текущий хост

Читайте также:  Обои для андроид религия

data — объект с данными типа Serializable

В этом же модуле реализована функция расширения фрагмента для получения данных, которые были переданы при выполнении действия навигации.

Также в этом модуле надо описать id хостов навигации, чтобы к ним был доступ из feature модулей. Для этого в директории ресурсов надо создать файл res/value/ids.xml

Отлично! Подготовка завершена, можно приступать к самой реализации навигации.

Простые переходы в feature-модулях

Сэмулируем типичное поведение экрана splash. Обычно с этого экрана идет переход либо к онбордингу, либо к главному экрану приложения, либо к экрану авторизации. Реализуем нечто похожее: пусть фрагмент фичи splash будет уметь переходить на экран онбординга и на главный экран по нажатию кнопки.

Для начала создади id для этих действий: запишем их в res/value/ids.xml модуля splash

Id для действий переходов я рекомендую создавать именно в модулях фич, которые будут использовать эти действия, а не в модуле shared:navigation. Это позволяет модулю знать только о необходимых действиях.

Теперь можно использовать созданные id для выполнения переходов.

Обратите внимание, что для выполнения перехода используется функция расширения из модуля shared:navigation.

Но чтобы этот переход заработал надо настроить глобальный хост и реализовать глобальную навигацию.

Глобальный хост

В нашей архитектуре всего одна Activity. Она будет содержать глобальный хост для фрагментов. Для этого нам ничего не потребуется реализовывать в самом коде Activity.

Хост добавить надо в ее разметке activity_main.xml

Глобальная навигация

Это навигация, которая происходит в глобальном хосте. Для ее реализации надо реализовать в модуле app граф навигации res/navigation/navigation_global.xml

Обратите внимание, что у каждого фрагмента есть набор action (действий) с помощью которых происходит переход между фрагментами. В действии указывается на какой фрагмент будет выполнен переход и как обрабатывать переход назад, например, при нажатии кнопки «Back».

И очень важно отметить, что id действий прописаны без знака +, то есть мы не создаем id в этом графе, а используем id, прописанные в feature модуле.

Прописанные id в модуле splash

Использование их в действиях глобального графа

Вложенный хост

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

В нашем примере во вложенном хосте будут фичи профиля и настроек.

Благодаря библиотеке navigation-ui, реализовать вложенную навигацию довольно просто.

В модуле main создадим меню для BottomNavigation в res/menu/menu_main.xml

Создадим граф навигации в res/navigation/navigation_main.xml

Здесь важно указать у фрагментов те же id что указаны в файле меню res/menu/menu_main.xml. И не забывать, что id действий брать из модулей фич.

Осталось добавить хост и меню в разметку фрагмента res/layout/fragment_main.xml

И в самом фрагменте настроить bottomNavigationView

Переходы между фрагментами из разных хостов

Довольно частый случай, когда надо перейти с экрана, который находится внутри вложенного хоста, на экран глобального хоста. Например, у нас есть главный экран c хостом для экранов главных фич: настроек и профиля.

И на экране настроек, который находится внутри хоста главного экрана (не глобальный хост, а глубже) надо выполнить переход на экран сплэша, который находится в глобальном хосте. Например это может понадобиться, если надо разлогинить текущего пользователя.

В этом случае также воспользуемся функцией расширения фрагмента, но укажем id глобального хоста. Мы имеем к нему доступ из фичи, так как он прописан в модуле shared:navigation.

Id действия по аналогии с предыдущим переходом прописан в самом модуле фичи res/values/ids.xml

Переходы между фрагментами с передачей и получением данных

Чтобы выполнить переход с передачей данных необходимо, чтобы данные можно было положить в bundle. Это могуг быть какие-то примитивные типы или объекты Serializable классов.

Выше я уже реализовал функцию расширения фрагмента для выполнения перехода, в которую можно передать объект Serializable класса. Аналогично вы можете реализовать передачу примитивных типов.

Чтобы передать объект Serializable класса надо чтобы модуль фичи, с которой происходит переход, и модуль фичи, на которую происходит переход, имели доступ к модулю с таким классом. В нашем случае создадим модуль shared:model где будет лежать Serializable класс Info.

Переход будет происходить с экрана profile на экран info. Создадим объект Info и передадим его в функцию расширения фрагмента.

И получим данные используя другую функцию расширения фрагмента, созданную ранее.

Так это будет выглядеть в приложении

Заметьте, что мы не указывали в каком хосте выполнить переход, и переход произошел в текущем хосте.

Заключение

Таким несложным способом можно организовать навигацию в вашем многомодульном проекте, используя Jetpack и пару функций расширения. Этот подход функционально не отличается от подхода, который я описывал ранее, но в использовании он намного проще и лаконичнее.

Источник

Оцените статью