-
|
Circuit Navigation is one of the really simple and powerful solutions I've been using in Navigation libraries. However, there is one concern when using it. package com.easyhooon.pokedex.feature.favorites
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import com.easyhooon.pokedex.core.data.api.repository.PokemonRepository
import com.easyhooon.pokedex.feature.favorites_detail.FavoritesDetailScreen // <- feature:favoritesDetail dependency
import com.slack.circuit.codegen.annotations.CircuitInject
import com.slack.circuit.retained.collectAsRetainedState
import com.slack.circuit.retained.rememberRetained
import com.slack.circuit.runtime.Navigator
import com.slack.circuit.runtime.presenter.Presenter
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import dagger.hilt.android.components.ActivityRetainedComponent
import kotlinx.collections.immutable.toImmutableList
class FavoritesPresenter @AssistedInject constructor(
@Assisted private val navigator: Navigator,
private val repository: PokemonRepository,
) : Presenter<FavoritesScreen.State> {
@Composable
override fun present(): FavoritesScreen.State {
val isLoading by rememberRetained { mutableStateOf(false) }
val favoritesPokemonList by repository.getFavoritesPokemonList().collectAsRetainedState(emptyList())
return FavoritesScreen.State(
isLoading = isLoading,
favoritesPokemonList = favoritesPokemonList.toImmutableList(),
) { event ->
when (event) {
is FavoritesScreen.Event.OnPokemonItemClick -> {
// direction of dependency: feature:favorites -> feature:favoritesDetail
navigator.goTo(FavoritesDetailScreen(pokemon = event.pokemon))
}
}
}
}
@CircuitInject(FavoritesScreen::class, ActivityRetainedComponent::class)
@AssistedFactory
fun interface Factory {
fun create(navigator: Navigator): FavoritesPresenter
}
}When navigator is injected from Presenter and moved to the next screen using functions such as Usually, feature modules are separated in units of screens, and in this case, this approach creates a dependency relationship between feature modules, as one module must rely on another to navigate to its screens. If the app grows in size and the navigation between screens is complicated, I think this can lead to cycle references between feature modules. Could you explain how to implement a solution that prevents cycle dependencies between feature modules when using Circuit Navigation? What are the common patterns or architectural approaches to handle this issue? I noticed that the tivi repository seems to have a solution for this, but it wasn't easy to understand because I'm not very skilled yet. ;) |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
|
The Tivi solution is basically what we'd advise. The gist of it is that you would define your Screen classes in a separate module that your different feature modules could depend on without depending on their actual presenter and UI implementations directly |
Beta Was this translation helpful? Give feedback.
The Tivi solution is basically what we'd advise. The gist of it is that you would define your Screen classes in a separate module that your different feature modules could depend on without depending on their actual presenter and UI implementations directly