Voyager: Navegação Multiplataforma e ViewModels (ScreenModel)

Italo Melo
3 min readApr 14, 2024

--

English Version

Intro

Projetado para Jetpack Compose, o Voyager simplifica a navegação e o gerenciamento de viewModels (screenModel) em várias plataformas. Neste artigo, vamos explorar os princípios fundamentais do Voyager, suas características e como ele remodela o desenvolvimento de interfaces de usuário em kotlin multiplataform.

Configuração

Voyager fornece múltiplas dependências conforme sua necessidade, cada uma com uma funcionalidade:

dependencies {
val voyagerVersion = "1.0.0"

// Multiplatform

// Navigator
implementation("cafe.adriel.voyager:voyager-navigator:$voyagerVersion")

// Screen Model
implementation("cafe.adriel.voyager:voyager-screenmodel:$voyagerVersion")

// BottomSheetNavigator
implementation("cafe.adriel.voyager:voyager-bottom-sheet-navigator:$voyagerVersion")

// TabNavigator
implementation("cafe.adriel.voyager:voyager-tab-navigator:$voyagerVersion")

// Transitions
implementation("cafe.adriel.voyager:voyager-transitions:$voyagerVersion")

// Android

// Koin integration
implementation("cafe.adriel.voyager:voyager-koin:$voyagerVersion")

// Hilt integration
implementation("cafe.adriel.voyager:voyager-hilt:$voyagerVersion")

// LiveData integration
implementation("cafe.adriel.voyager:voyager-livedata:$voyagerVersion")

// Desktop + Android

// Kodein integration
implementation("cafe.adriel.voyager:voyager-kodein:$voyagerVersion")

// RxJava integration
implementation("cafe.adriel.voyager:voyager-rxjava:$voyagerVersion")
}

Para este tutorial, vamos utilizar o Navigator e o ScreenModel, então podemos começar adicionando essas implementações ao nosso arquivo de catálogo de versões:

[versions]
voyager = "1.0.0"

[libraries]
voyager-navigator = { module = "cafe.adriel.voyager:voyager-navigator", version.ref = "voyager" }
voyager-screenModel = { module = "cafe.adriel.voyager:voyager-screenmodel", version.ref = "voyager" }

Agora vamos importar essas novas bibliotecas no nosso arquivo build.gradle do Compose:

commonMain.dependencies {
implementation(libs.voyager)
implementation(libs.voyager.screenModel)
}

Entendendo ScreenModel e ViewModel

ScreenModel é semelhante a uma ViewModel: projetado para armazenar e gerenciar dados relacionados à interface do usuário de forma consciente no ciclo de vida. Também permite que os dados sobrevivam a mudanças de configuração, como rotações de tela. (Documentação do Voyager)

Com isso em mente, vamos criar um ScreenModel simples para buscar alguns dados:

import cafe.adriel.voyager.core.model.ScreenModel
import cafe.adriel.voyager.core.model.screenModelScope

class DataScreenModel() : ScreenModel {
fun fetchData(){
screenModelScope.launch {
//fetch data code
}
}
}

Note que estamos usando screenModelScope em vez de viewModelScope, mas eles se comportam de forma semelhante.

Isso é tudo, esta é uma implementação simples de um screenModel.

Navegando Telas

Primeiro, vamos envolver nosso composable principal por um Navigator e, no construtor, passar a primeira tela que queremos exibir, neste caso será DataScreen.

import cafe.adriel.voyager.navigator.Navigator

@Composable
fun App() {
Navigator(DataScreen())
}

Agora, vamos criar nossa DataScreen implementando a interface Screen e substituindo a função content (isso será exibido na tela). Além disso, nesta tela queremos navegar para outra tela. Para fazer isso, queremos importar o LocalNavigator e chamar a função push para empurrar uma nova tela passando os parâmetros necessários.

import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.navigator.LocalNavigator

class DataScreen : Screen {
@Composable
override fun Content {
val navigator = LocalNavigator.currentOrThrow
// em um clique de botão ou evento chamar :
navigator.push(DataDetailsScreen(data))
}
}

Para obter os parâmetros, nossa segunda tela será uma data class. Este será o resultado:

import cafe.adriel.voyager.core.screen.Screen

data class DataDetailScreen(data : Data) : Screen {
@Composable
override fun Content {
// mostrar dados no composable
// em um clique de botão ou evento chamar :
navigator.pop()
}
}

Se desejar voltar à tela anterior, use a função navigator.pop().

Transições

Se você quiser adicionar transições a este navigator, primeiro precisamos adicionar a dependência de transições.

[versions]
voyager = "1.0.0"

[libraries]
voyager-transitions = { module = "cafe.adriel.voyager:voyager-transitions", version.ref = "voyager" }
commonMain.dependencies {
implementation(libs.voyager.transitions)
}

Agora vamos aplicar a transição no componente Navigator no Composable do aplicativo:

@Composable
fun App() {
Navigator(DataScreen()) { navigator ->
SlideTransition(navigator)
}
}

Neste caso, estamos usando a SlideTransition. Para ver as transições disponíveis, consulte a documentação.

É isso! Esta é uma implementação simples do Voyager. Tenha em mente que existem múltiplas implementações e suporte para Koin, Hilt, Codein, etc. Esta é uma biblioteca muito bem documentada, então visite a documentação para mais detalhes.

--

--