Форум для тех, кто программирует под Android
Anonymous
Hilt Navigation Compose и ViewModel
Сообщение
Anonymous » 30 дек 2024, 15:15
Я пытался следовать примерам в документации по Android, но не смог реализовать навигацию с помощью Navigation Compose, ViewModel и Hilt. Никаких ошибок не возникает, и в NavigationScreen LaunchedERffect не запускается при генерации ViewModel.
Composables:
Код: Выделить всё
@HiltAndroidApp
class MyApplication : Application() {}
@Serializable
object NavScreen
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
val navController = rememberNavController()
PhotosSyncTheme {
NavHost(
navController = navController,
startDestination = NavScreen
) {
composable { NavigationScreen(navController) }
composable { HomeScreen() }
composable { Settings() }
}
}
}
}
}
@Composable
fun NavigationScreen(navController: NavController) {
val navViewModel = hiltViewModel()
val navigationEvent by navViewModel.navigationEvents.collectAsState(initial = NavigationEvent.NavigateToHome)
LaunchedEffect(navigationEvent) {
Log.d("Navigation Screen", navigationEvent.toString())
navigationEvent.let { event ->
Log.d("Navigation Screen", event.toString())
when (event) {
is NavigationEvent.NavigateBack -> navController.popBackStack()
NavigationEvent.NavigateToHome -> navController.navigate(NavigationEvent.NavigateToHome)
NavigationEvent.NavigateToSettings -> navController.navigate(NavigationEvent.NavigateToSettings)
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HomeScreen() {
val navViewModel = hiltViewModel()
var selectedItem by remember { mutableIntStateOf(0) }
Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = {
TopAppBar(title = { Text("Photos Sync") }, actions = {
IconButton(onClick = {
navViewModel.navigateToSettings()
}) {
Icon(
imageVector = Icons.Filled.Settings,
contentDescription = "Settings icon"
)
}
})
}
)
{ }
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Settings() {
val viewModel = hiltViewModel()
Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = {
TopAppBarWithBack(title = "Definições")
}
)
{ }
}
ViewModel:
Код: Выделить всё
@HiltViewModel
class NavigationViewModel @Inject constructor() : ViewModel() {
private val _navigationEvents = MutableSharedFlow()
val navigationEvents: SharedFlow = _navigationEvents.asSharedFlow()
fun navigateBack() {
viewModelScope.launch { _navigationEvents.emit(NavigationEvent.NavigateBack) }
}
fun navigateToHome() {
viewModelScope.launch { _navigationEvents.emit(NavigationEvent.NavigateToHome) }
}
fun navigateToSettings() {
viewModelScope.launch {
Log.d("Navigation ViewModel", "Emit Navigate To Settings")
try {
_navigationEvents.emit(NavigationEvent.NavigateToSettings)
} catch (e: Exception) {
Log.e("Navigation ViewModel", "Error emitting navigation event")
} finally {
Log.d("Navigation ViewModel", "done Emit Navigate To Settings")
}
}
}
fun navigateTo(event: NavigationEvent) {
viewModelScope.launch { _navigationEvents.emit(event) }
}
sealed class NavigationEvent {
@Serializable
object NavigateBack : NavigationEvent()
@Serializable
object NavigateToHome : NavigationEvent()
@Serializable
object NavigateToSettings : NavigationEvent()
}
}
Я ожидал, что когда я нажму кнопку настроек, составной элемент настроек будет помещен в начало стека составных элементов с помощью navController.navigate
Подробнее здесь:
https://stackoverflow.com/questions/793 ... -viewmodel
1735560945
Anonymous
Я пытался следовать примерам в документации по Android, но не смог реализовать навигацию с помощью Navigation Compose, ViewModel и Hilt. Никаких ошибок не возникает, и в NavigationScreen LaunchedERffect не запускается при генерации ViewModel. Composables: [code]@HiltAndroidApp class MyApplication : Application() {} @Serializable object NavScreen @AndroidEntryPoint class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { val navController = rememberNavController() PhotosSyncTheme { NavHost( navController = navController, startDestination = NavScreen ) { composable { NavigationScreen(navController) } composable { HomeScreen() } composable { Settings() } } } } } } @Composable fun NavigationScreen(navController: NavController) { val navViewModel = hiltViewModel() val navigationEvent by navViewModel.navigationEvents.collectAsState(initial = NavigationEvent.NavigateToHome) LaunchedEffect(navigationEvent) { Log.d("Navigation Screen", navigationEvent.toString()) navigationEvent.let { event -> Log.d("Navigation Screen", event.toString()) when (event) { is NavigationEvent.NavigateBack -> navController.popBackStack() NavigationEvent.NavigateToHome -> navController.navigate(NavigationEvent.NavigateToHome) NavigationEvent.NavigateToSettings -> navController.navigate(NavigationEvent.NavigateToSettings) } } } } @OptIn(ExperimentalMaterial3Api::class) @Composable fun HomeScreen() { val navViewModel = hiltViewModel() var selectedItem by remember { mutableIntStateOf(0) } Scaffold( modifier = Modifier.fillMaxSize(), topBar = { TopAppBar(title = { Text("Photos Sync") }, actions = { IconButton(onClick = { navViewModel.navigateToSettings() }) { Icon( imageVector = Icons.Filled.Settings, contentDescription = "Settings icon" ) } }) } ) { } } @OptIn(ExperimentalMaterial3Api::class) @Composable fun Settings() { val viewModel = hiltViewModel() Scaffold( modifier = Modifier.fillMaxSize(), topBar = { TopAppBarWithBack(title = "Definições") } ) { } } [/code] ViewModel: [code]@HiltViewModel class NavigationViewModel @Inject constructor() : ViewModel() { private val _navigationEvents = MutableSharedFlow() val navigationEvents: SharedFlow = _navigationEvents.asSharedFlow() fun navigateBack() { viewModelScope.launch { _navigationEvents.emit(NavigationEvent.NavigateBack) } } fun navigateToHome() { viewModelScope.launch { _navigationEvents.emit(NavigationEvent.NavigateToHome) } } fun navigateToSettings() { viewModelScope.launch { Log.d("Navigation ViewModel", "Emit Navigate To Settings") try { _navigationEvents.emit(NavigationEvent.NavigateToSettings) } catch (e: Exception) { Log.e("Navigation ViewModel", "Error emitting navigation event") } finally { Log.d("Navigation ViewModel", "done Emit Navigate To Settings") } } } fun navigateTo(event: NavigationEvent) { viewModelScope.launch { _navigationEvents.emit(event) } } sealed class NavigationEvent { @Serializable object NavigateBack : NavigationEvent() @Serializable object NavigateToHome : NavigationEvent() @Serializable object NavigateToSettings : NavigationEvent() } } [/code] Я ожидал, что когда я нажму кнопку настроек, составной элемент настроек будет помещен в начало стека составных элементов с помощью navController.navigate Подробнее здесь: [url]https://stackoverflow.com/questions/79316638/hilt-navigation-compose-and-viewmodel[/url]