Код: Выделить всё
val userId = "userId"
NavHost(
navController = navController,
startDestination = "main_graph/$userId"
) {
navigation(
startDestination = "home/{userId}",
route = "main_graph/{userId}",
) {
composable(
route = "home/{userId}",
arguments = listOf(
navArgument("userId") { type = NavType.StringType }
)
)
{ backStackEntry ->
val viewModel = backStackEntry.sharedViewModel(navController)
LaunchedEffect(userId) {
viewModel.initialize(userId)
}
HomeScreen(navController, userId)
}
composable(
route = "chat/{userId}",
arguments = listOf(
navArgument("userId") { type = NavType.StringType }
)
)
{ backStackEntry ->
val viewModel = backStackEntry.sharedViewModel(navController)
ChatScreen(viewModel)
}
}
}
Код: Выделить всё
@Composable
inline fun NavBackStackEntry.sharedViewModel(
navController: NavHostController,
): T {
val navGraphRoute = destination.parent?.route ?: return hiltViewModel()
val parentEntry = remember(this) {
navController.getBackStackEntry(navGraphRoute)
}
return hiltViewModel(parentEntry)
}
Код: Выделить всё
@HiltViewModel
class ChatViewModel @Inject constructor(
private val simpleUseCase: SimpleUseCase
) : ViewModel() {
private val _conversationListState = MutableStateFlow(emptyList())
val conversationListState = _conversationListState.asStateFlow()
private val _initialized = false
fun initialize(userId: String) {
if (_initialized) return
getConversationList(userId)
}
private fun getConversationList(userId: String) {
simpleUseCase().onEach { response ->
// Update the conversation list state with the new data
_conversationListState.value = response
Log.d("ChatViewModel", "Conversation list updated with response: $response")
}.launchIn(viewModelScope)
}
}
Вот вариант использования (я думаю, что ошибка может быть на этом):
Код: Выделить всё
class SimpleUseCase @Inject constructor() {
operator fun invoke(): Flow = channelFlow {
var resConversations: MutableList = mutableListOf()
send(resConversations)
coroutineScope {
launch {
// Simulate fetching conversation list
val conversations = listOf(
Conversation("Hello! How are you?"),
Conversation("Let's meet tomorrow."),
Conversation("Did you finish the project?")
)
resConversations = conversations.toMutableList()
send(resConversations)
}
launch {
// Simulate a delay before updating the conversation list
kotlinx.coroutines.delay(15000L)
val conversations = listOf(
Conversation("New message after delay!"),
Conversation("Another message after delay!")
)
resConversations += conversations
send(resConversations)
}
launch {
// Simulate another delay before updating the conversation list again
kotlinx.coroutines.delay(30000L)
resConversations[resConversations.size - 1] =
Conversation("Updated message after another delay!")
send(resConversations)
}
}
}
}
< /code>
Вот код экранов: < /p>
@Composable
fun HomeScreen(
navController: NavController,
userId: String
) {
Button(onClick = { navController.navigate("chat/$userId") }) {
Text("Click me to go to Chat Screen")
}
}
@Composable
fun ChatScreen(
viewModel: ChatViewModel = hiltViewModel()
) {
val conversationListState by viewModel.conversationListState.collectAsStateWithLifecycle()
LazyColumn {
items(
conversationListState
) { conversation ->
Text(conversation.message)
}
}
}
< /code>
Когда приложение запускается, я нажал кнопку, чтобы перейти на экран чата. Содержание первого блока запуска в варианте использования загружается и показано правильно. Тем не менее, после этого, когда второй и третий запуск блокируют значение, The SpearchListState
Подробнее здесь: https://stackoverflow.com/questions/796 ... s-the-same