- Экран А.
- Экран Б.
Этот поток собирается с помощью CollectAsStateWithLifecycle в составной функции Navigator. Затем этот Navigator использует NavHostController для навигации.
Если я нажимаю кнопку «Назад», приложение отображает Экран B, и я вернемся к Экрану A.
Как ни странно, во время появления вызывается NavigationModel#onCleared. Я выбрал эту трассировку стека вручную:
Код: Выделить всё
com.myapp.presentation.viewmodels.NavigationViewModel.onCleared(NavigationViewModel.kt:59)
androidx.lifecycle.ViewModel.clear(ViewModel.java:202)
androidx.lifecycle.ViewModelStore.clear(ViewModelStore.kt:69)
androidx.navigation.NavControllerViewModel.clear(NavControllerViewModel.kt:33)
androidx.navigation.NavController$NavControllerNavigatorState.markTransitionComplete(NavController.kt:359)
androidx.navigation.compose.ComposeNavigator.onTransitionComplete(ComposeNavigator.kt:8androidx.navigation.compose.NavHostKt$NavHost$15.invokeSuspend(NavHost.kt:314)
Пожалуйста, взгляните на мой код
Код: Выделить всё
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyAppTheme {
Surface(modifier = Modifier.fillMaxSize()) {
Box(modifier = Modifier.fillMaxSize()) {
SetupAppNavigation()
}
}
}
}
}
}
@Composable
fun SetupAppNavigation() {
val navController = rememberNavController()
Navigator(navHostController = navController) // sits on top of the nav host
NavHost(
navController = navController,
startDestination = "screen_a",
) {
composable(route = "screen_a") {
ScreenARoute()
}
composable(route = "screen_b") {
ScreenBRoute()
}
}
}
@Composable
fun Navigator(
navHostController: NavHostController,
) {
val navigationViewModel: NavigationViewModel = koinViewModel()
val navDirection: NavigationUiEvent? by navigationViewModel.state.collectAsStateWithLifecycle(initialValue = null)
when (val nav = navDirection) {
is NavigationUiEvent.ScreenB -> navHostController.navigate(route = "screen_b")
null -> Unit // Nothing to do here
}
}
class NavigationViewModel internal constructor() : ViewModel(), NavigationUiEventHandler, KoinComponent {
private val module: Module by lazy {
module {
single { this@NavigationViewModel } bind NavigationUiEventHandler::class
}
}
private val events = MutableSharedFlow()
val state: SharedFlow = events
.onStart { getKoin().loadModules(listOf(module)) }
.onCompletion { getKoin().unloadModules(listOf(module)) }
.shareIn(
scope = viewModelScope,
started = SharingStarted.Eagerly,
)
override fun handleEvent(event: NavigationUiEvent) {
viewModelScope.launch {
events.emit(event)
}
}
override fun onCleared() {
super.onCleared()
println("DEBUG >> NavigationViewModel CLEARED so YEAH GOODBYE !")
}
}
# KOIN INJECTION #
val viewModelsModule = module {
viewModeOf(::NavigationViewModel)
viewModeOf(::ScreenAViewModel)
viewModeOf(::ScreenBViewModel)
}
class MyApp: Application() {
override fun onCreate() {
super.onCreate()
startKoin {
androidLogger()
androidContext(this@ MyApp)
modules(
listOf(
viewModelsModule,
...
)
)
}
}
}
Код: Выделить всё
DEBUG >> NavigationViewModel CLEARED so YEAH GOODBYE !
Почему?
Честно говоря, я не знаю не понимаю, почему NavControllerViewModel (из трассировки стека) очищает мою NavigationViewModel даже если она явно не привязана к конкретному экрану как часть моего графа навигации.< /п>
Подробнее здесь: https://stackoverflow.com/questions/791 ... from-the-b
Мобильная версия