Reputation: 1
In Jetpack Compose, what would be a proper way to fetch all required data before a composable used to edit this data is created?
What I have are two composables, one is supposed to fetch all required data that is to be displayed, the child is supposed to allow the user to edit this data via form elements.
The data is fetched in the view model and locally stored in the child composable as a rememberSaveable()
during editing:
ViewModel contains:
private val _userFetchedForEditing = MutableStateFlow<User?>(null)
val userFetchedForEditing: StateFlow<User?> = _userFetchedForEditing.asStateFlow()
fun fetchUserForEditingByName(name: String) {
_userFetchedForEditing.value = null
viewModelScope.launch {
_userFetchedForEditing.value = userRepository.getUserByName(name).firstOrNull()
}
}
Compose code parent:
composable(
route = "${Screen.UserEditor.route}?userName={userName}",
arguments = listOf(navArgument("userName") {
type = NavType.StringType
nullable = false
}),
) { navBackStackEntry ->
val userName: String? = navBackStackEntry.arguments?.getString("userName")
LaunchedEffect(userName) {
userName?.let { viewModel.fetchUserForEditingByName(it) }
}
val userFetchedForEditing by viewModel.userFetchedForEditing.collectAsState()
if (userFetchedForEditing == null) {
LoadingScreen()
} else {
UserEditor(viewModel, navController, modifier, userFetchedForEditing)
}
}
Compose code child:
@Composable
private fun UserEditor(
viewModel: MainViewModel,
navController: NavHostController,
modifier: Modifier = Modifier,
givenInput: User? = null,
) {
var editableInputUser by rememberSaveable(saver = userSaver) {
mutableStateOf(givenInput ?: User())
}
//this causes a visible screen refresh of the shown user after a couple milliseconds, but is needed or the editableInputUser is not updated to the givenInput sometimes
LaunchedEffect(givenInput) {
editableInputUser = givenInput ?: User()
}
UserEditorForm(
//takes editableInputUser and displays forms for updating values
)
}
My concrete question is: What would be the way to go here, to allow displaying and editing the user using Jetpack Compose?
It currently feels like I have to abuse the LaunchedEffect to yank the displayed data into what should be displayed.
Upvotes: 0
Views: 121
Reputation: 15763
You already have most of what you need: You display the LoadingScreen
until the data is available, and then call UserEditor
when it is loaded.
Some minor things seem to be a little bit off, though. Why is the UserEditor
's givenInput
parameter nullable? Make it non-nullable and then call it like this:
userFetchedForEditing.also {
if (it == null) {
LoadingScreen()
} else {
UserEditor(viewModel, navController, modifier, it)
}
}
Also, I don't see why the LaunchedEffect is necessary. Do you expect the givenInput
to change by some other means while the user is editing it? And do you really want to overwrite everything the user entered so far when that happens?
And finally, it seems easier to store the editableInputUser
in the view model (as a MutableStateFlow) instead of jumping through hoops with rememberSaveable
and a custom saver.
Upvotes: 0