Anonymous
Navigieren von einem Bildschirm zum anderen mit parametrisierten serialisierbaren Datenklassen [Duplikat]
Post
by Anonymous » 15 Feb 2025, 15:12
Ich verwende das Navigationsdiagramm mit serialisierbaren Objekten und Datenklassen, um einen Bildschirm auf einen anderen zu geben. Ich benutze das One ActivTiy -Muster und alle meine ViewModels sind mit dem Griff auf ihre Wiederholungsbildschirme gesammelt. Ich habe gesehen, dass ich das ohne Probleme tun kann, wenn ich vom Anmeldebildschirm zum Startbildschirm navigiere. Sam zum Spitznamenbildschirm. Wenn ich vom Spitznamen nach Hause gehe, bekomme ich den Fehler: < /p>
Code: Select all
FATAL EXCEPTION: main
Process: com.example.hearty, PID: 23649
kotlinx.serialization.SerializationException: Serializer for class 'Companion' is not found. Please ensure that class is marked as '@Serializable' and that the serialization compiler plugin is applied.
< /code>
Jetzt habe ich alles in meinem Modul und in meinem Modul und in meinen Bibliotheken korrekt implementiert und alle Abhängigkeiten sind sehr gut integriert, Ursache Navigation funktionieren, aber ich habe das lästige Ding beobachtet, dass ich, wenn ich den Popupto entferte, wenn ich aus dem Spitznamen navigiere Zu Hause funktioniert es gut. Ich habe keine Orte zu fragen, KI ist auch nicht sehr hilfreich. >@Composable
fun LoginScreen(navController: NavController) {
val viewModel = hiltViewModel()
val snackbarHostState = remember { SnackbarHostState() }
val loginResult by viewModel.loginResult.observeAsState()
val nickname by viewModel.nickname.collectAsState()
val formFieldMaxLength = 24
val isOnline = viewModel.isOnline.collectAsState()
val noInternetMessage = stringResource(R.string.snackbarMessageInfo0)
LaunchedEffect(loginResult) {
loginResult?.let {
if(it.message != "") {
if (it.show) {
snackbarHostState.showSnackbar(
message = it.message,
withDismissAction = it.withDismissAction,
duration = it.duration
)
it.show = false
}
}
else{
Log.d("LoginScreen", "$nickname")
if (nickname == ""){
navController.navigate(Nickname(viewModel.idUser.value!!)){
popUpTo(Login){
inclusive = true
}
}
}
else {
navController.navigate(Home(viewModel.idUser.value!!)){
popUpTo(Login){
inclusive = true
}
}
}
}
}
}
LaunchedEffect(nickname) {
nickname?.let{
if (it != " "){
if(it != ""){
navController.navigate(Home(viewModel.idUser.value!!)) {
popUpTo(Login) {
inclusive = true
}
}
}
else{
navController.navigate(Nickname(viewModel.idUser.value!!)) {
popUpTo(Login) {
inclusive = true
}
}
}
}
}
}
LaunchedEffect(isOnline) {
isOnline.value.let{
if (!it){
snackbarHostState.showSnackbar(
message = noInternetMessage,
withDismissAction = true,
duration = SnackbarDuration.Short
)
}
}
}
Scaffold(
modifier = Modifier
.fillMaxSize()
.imePadding(),
containerColor = hearty_theme_light_primary,
snackbarHost = {
SnackbarHost(
hostState = snackbarHostState,
snackbar = { data ->
Snackbar(
snackbarData = data,
containerColor = if (loginResult != null) loginResult!!.color else Color(0)
)
})
}
) {
Column(modifier = Modifier.padding(it)) {
Image(
painter = painterResource(
when (isOnline.value) {
true -> R.drawable.img_login_art
else -> R.drawable.no_internet
}
),
contentDescription = "Login greet art",
modifier = Modifier
.fillMaxWidth()
.padding(all = 15.dp)
.weight(.35f)
)
Surface(
shape = RoundedCornerShape(
topStart = 30.dp,
topEnd = 30.dp,
bottomStart = 30.dp,
bottomEnd = 30.dp
),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 25.dp)
.padding(bottom = 25.dp)
.weight(.65f),
shadowElevation = 30.dp,
) {
Column(
modifier = Modifier
.verticalScroll(rememberScrollState())
.padding(horizontal = 25.dp)
.padding(top = 25.dp),
verticalArrangement = Arrangement.SpaceBetween
) {
Column(
modifier = Modifier
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
val user = viewModel.getUser()
val pass = viewModel.getPass()
val acceptedRegex = Regex("[\\w*.,?!\\|/-=+@#$%^&()\\[\\]{}]*")
ClearTextField(
user,
acceptedRegex,
{newUsername -> viewModel.updateUser(newUsername)},
R.string.formLoginUsername,
"....."
)
TextFieldSupportMaxLength(
textFieldValue = user,
maxLength = formFieldMaxLength
)
HiddenTextField(
pass,
acceptedRegex,
{newPassword -> viewModel.updatePass(newPassword)},
R.string.formLoginPassword,
"*****"
)
TextFieldSupportMaxLength(
Modifier.fillMaxWidth(),
textFieldValue = pass,
maxLength = formFieldMaxLength
)
MainButtonForm(
{ viewModel.checkCredentials() },
isOnline.value,
stringResource(R.string.buttonLogin).uppercase()
)
}
Row(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 25.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
) {
Text(
text = stringResource(R.string.formLoginToRegister),
color = Color.Black,
fontSize = 14.sp,
fontWeight = FontWeight.Normal
)
TextButton(
onClick = { navController.navigate(Register) },
contentPadding = PaddingValues(3.dp),
enabled = isOnline.value,
content = {
Text(
text = stringResource(R.string.buttonRegister).uppercase(),
color = if (isOnline.value) hearty_theme_light_primary
else hearty_theme_button_onInactive,
fontSize = 14.sp,
fontWeight = FontWeight.ExtraBold,
fontStyle = FontStyle.Italic
)
}
)
}
}
}
}
}
}
Spitzname -Bildschirm
Code: Select all
@Composable
fun NicknameScreen(
navController: NavController){
val viewModel = hiltViewModel()
val snackbarHostState = remember { SnackbarHostState() }
val updateResult by viewModel.updateResult.observeAsState()
val isEnabledProceed by viewModel.isEnabledProceed.collectAsState()
val formFieldMaxLength = 24
val id = navController.currentBackStackEntry?.arguments?.getString("id") ?: ""
LaunchedEffect(updateResult) {
updateResult?.let {
if (it.message != "") {
if (it.show) {
snackbarHostState.showSnackbar(
message = it.message,
withDismissAction = it.withDismissAction,
duration = it.duration
)
it.show = false
}
}
else{
Log.d("NicknameScreen", "USER ID: {${viewModel.id}}")
navController.navigate(Home(viewModel.id)) {
popUpTo(Nickname){
inclusive = true
}
}
}
}
}
Scaffold(
modifier = Modifier
.fillMaxSize()
.imePadding(),
containerColor = hearty_theme_light_primary,
snackbarHost = {
SnackbarHost(
hostState = snackbarHostState,
snackbar = { data ->
Snackbar(
snackbarData = data,
containerColor = updateResult?.color ?: Color(0)
)
})
}
) {
Column(
modifier = Modifier
.padding(it)
.padding(all= 25.dp)
.fillMaxSize(),
verticalArrangement = Arrangement.Center
) {
Surface(
shape = RoundedCornerShape(
topStart = 30.dp,
topEnd = 30.dp,
bottomStart = 30.dp,
bottomEnd = 30.dp
) ) {
Column(modifier = Modifier.padding(all= 25.dp)) {
val nickname = viewModel.nickname.observeAsState()
val acceptedRegex = Regex("[\\w*., ?!'\"|/-=+@#$%^&()\\[\\]{}]*")
Text(
text = stringResource(R.string.formChooseNicknameFormTitle),
fontSize = 24.sp,
color = Color.Black,
fontWeight = FontWeight.ExtraBold,
textAlign = TextAlign.Center,
modifier= Modifier.padding(bottom= 10.dp)
)
ClearTextField(
value = nickname.value!!,
acceptedRegex = acceptedRegex,
onValueChange = { newValue -> viewModel.setNickname(newValue) },
stringResource = R.string.formChooseNickname,
placeholder = ".....",
formFieldMaxLength = formFieldMaxLength
)
TextFieldSupportMaxLength(
textFieldValue = nickname.value!!,
maxLength = formFieldMaxLength
)
MainButtonForm(
{
if(id != ""){
viewModel.checkNickname(id)
}
else{
viewModel.setUpdateResultError(R.string.formNicknameIdError)
}
},
isEnabledProceed,
stringResource(R.string.buttonProceed)
)
}
}
}
}
}
Navigationsobjekte
Code: Select all
//Routes
@Serializable
object Login
@Serializable
object Register
@Serializable
data class Nickname(val id: String? = null)
@Serializable
data class Home(val id: String? = null)
@Serializable
object HomeCookbooks
@Serializable
object HomeCooking
@Serializable
object HomeSearch
1739628732
Anonymous
Ich verwende das Navigationsdiagramm mit serialisierbaren Objekten und Datenklassen, um einen Bildschirm auf einen anderen zu geben. Ich benutze das One ActivTiy -Muster und alle meine ViewModels sind mit dem Griff auf ihre Wiederholungsbildschirme gesammelt. Ich habe gesehen, dass ich das ohne Probleme tun kann, wenn ich vom Anmeldebildschirm zum Startbildschirm navigiere. Sam zum Spitznamenbildschirm. Wenn ich vom Spitznamen nach Hause gehe, bekomme ich den Fehler: < /p> [code]FATAL EXCEPTION: main Process: com.example.hearty, PID: 23649 kotlinx.serialization.SerializationException: Serializer for class 'Companion' is not found. Please ensure that class is marked as '@Serializable' and that the serialization compiler plugin is applied. < /code> Jetzt habe ich alles in meinem Modul und in meinem Modul und in meinen Bibliotheken korrekt implementiert und alle Abhängigkeiten sind sehr gut integriert, Ursache Navigation funktionieren, aber ich habe das lästige Ding beobachtet, dass ich, wenn ich den Popupto entferte, wenn ich aus dem Spitznamen navigiere Zu Hause funktioniert es gut. Ich habe keine Orte zu fragen, KI ist auch nicht sehr hilfreich. >@Composable fun LoginScreen(navController: NavController) { val viewModel = hiltViewModel() val snackbarHostState = remember { SnackbarHostState() } val loginResult by viewModel.loginResult.observeAsState() val nickname by viewModel.nickname.collectAsState() val formFieldMaxLength = 24 val isOnline = viewModel.isOnline.collectAsState() val noInternetMessage = stringResource(R.string.snackbarMessageInfo0) LaunchedEffect(loginResult) { loginResult?.let { if(it.message != "") { if (it.show) { snackbarHostState.showSnackbar( message = it.message, withDismissAction = it.withDismissAction, duration = it.duration ) it.show = false } } else{ Log.d("LoginScreen", "$nickname") if (nickname == ""){ navController.navigate(Nickname(viewModel.idUser.value!!)){ popUpTo(Login){ inclusive = true } } } else { navController.navigate(Home(viewModel.idUser.value!!)){ popUpTo(Login){ inclusive = true } } } } } } LaunchedEffect(nickname) { nickname?.let{ if (it != " "){ if(it != ""){ navController.navigate(Home(viewModel.idUser.value!!)) { popUpTo(Login) { inclusive = true } } } else{ navController.navigate(Nickname(viewModel.idUser.value!!)) { popUpTo(Login) { inclusive = true } } } } } } LaunchedEffect(isOnline) { isOnline.value.let{ if (!it){ snackbarHostState.showSnackbar( message = noInternetMessage, withDismissAction = true, duration = SnackbarDuration.Short ) } } } Scaffold( modifier = Modifier .fillMaxSize() .imePadding(), containerColor = hearty_theme_light_primary, snackbarHost = { SnackbarHost( hostState = snackbarHostState, snackbar = { data -> Snackbar( snackbarData = data, containerColor = if (loginResult != null) loginResult!!.color else Color(0) ) }) } ) { Column(modifier = Modifier.padding(it)) { Image( painter = painterResource( when (isOnline.value) { true -> R.drawable.img_login_art else -> R.drawable.no_internet } ), contentDescription = "Login greet art", modifier = Modifier .fillMaxWidth() .padding(all = 15.dp) .weight(.35f) ) Surface( shape = RoundedCornerShape( topStart = 30.dp, topEnd = 30.dp, bottomStart = 30.dp, bottomEnd = 30.dp ), modifier = Modifier .fillMaxWidth() .padding(horizontal = 25.dp) .padding(bottom = 25.dp) .weight(.65f), shadowElevation = 30.dp, ) { Column( modifier = Modifier .verticalScroll(rememberScrollState()) .padding(horizontal = 25.dp) .padding(top = 25.dp), verticalArrangement = Arrangement.SpaceBetween ) { Column( modifier = Modifier .fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { val user = viewModel.getUser() val pass = viewModel.getPass() val acceptedRegex = Regex("[\\w*.,?!\\|/-=+@#$%^&()\\[\\]{}]*") ClearTextField( user, acceptedRegex, {newUsername -> viewModel.updateUser(newUsername)}, R.string.formLoginUsername, "....." ) TextFieldSupportMaxLength( textFieldValue = user, maxLength = formFieldMaxLength ) HiddenTextField( pass, acceptedRegex, {newPassword -> viewModel.updatePass(newPassword)}, R.string.formLoginPassword, "*****" ) TextFieldSupportMaxLength( Modifier.fillMaxWidth(), textFieldValue = pass, maxLength = formFieldMaxLength ) MainButtonForm( { viewModel.checkCredentials() }, isOnline.value, stringResource(R.string.buttonLogin).uppercase() ) } Row( modifier = Modifier .fillMaxWidth() .padding(bottom = 25.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center, ) { Text( text = stringResource(R.string.formLoginToRegister), color = Color.Black, fontSize = 14.sp, fontWeight = FontWeight.Normal ) TextButton( onClick = { navController.navigate(Register) }, contentPadding = PaddingValues(3.dp), enabled = isOnline.value, content = { Text( text = stringResource(R.string.buttonRegister).uppercase(), color = if (isOnline.value) hearty_theme_light_primary else hearty_theme_button_onInactive, fontSize = 14.sp, fontWeight = FontWeight.ExtraBold, fontStyle = FontStyle.Italic ) } ) } } } } } } [/code] [b] Spitzname -Bildschirm [/b] [code]@Composable fun NicknameScreen( navController: NavController){ val viewModel = hiltViewModel() val snackbarHostState = remember { SnackbarHostState() } val updateResult by viewModel.updateResult.observeAsState() val isEnabledProceed by viewModel.isEnabledProceed.collectAsState() val formFieldMaxLength = 24 val id = navController.currentBackStackEntry?.arguments?.getString("id") ?: "" LaunchedEffect(updateResult) { updateResult?.let { if (it.message != "") { if (it.show) { snackbarHostState.showSnackbar( message = it.message, withDismissAction = it.withDismissAction, duration = it.duration ) it.show = false } } else{ Log.d("NicknameScreen", "USER ID: {${viewModel.id}}") navController.navigate(Home(viewModel.id)) { popUpTo(Nickname){ inclusive = true } } } } } Scaffold( modifier = Modifier .fillMaxSize() .imePadding(), containerColor = hearty_theme_light_primary, snackbarHost = { SnackbarHost( hostState = snackbarHostState, snackbar = { data -> Snackbar( snackbarData = data, containerColor = updateResult?.color ?: Color(0) ) }) } ) { Column( modifier = Modifier .padding(it) .padding(all= 25.dp) .fillMaxSize(), verticalArrangement = Arrangement.Center ) { Surface( shape = RoundedCornerShape( topStart = 30.dp, topEnd = 30.dp, bottomStart = 30.dp, bottomEnd = 30.dp ) ) { Column(modifier = Modifier.padding(all= 25.dp)) { val nickname = viewModel.nickname.observeAsState() val acceptedRegex = Regex("[\\w*., ?!'\"|/-=+@#$%^&()\\[\\]{}]*") Text( text = stringResource(R.string.formChooseNicknameFormTitle), fontSize = 24.sp, color = Color.Black, fontWeight = FontWeight.ExtraBold, textAlign = TextAlign.Center, modifier= Modifier.padding(bottom= 10.dp) ) ClearTextField( value = nickname.value!!, acceptedRegex = acceptedRegex, onValueChange = { newValue -> viewModel.setNickname(newValue) }, stringResource = R.string.formChooseNickname, placeholder = ".....", formFieldMaxLength = formFieldMaxLength ) TextFieldSupportMaxLength( textFieldValue = nickname.value!!, maxLength = formFieldMaxLength ) MainButtonForm( { if(id != ""){ viewModel.checkNickname(id) } else{ viewModel.setUpdateResultError(R.string.formNicknameIdError) } }, isEnabledProceed, stringResource(R.string.buttonProceed) ) } } } } } [/code] [b] Navigationsobjekte [/b] [code]//Routes @Serializable object Login @Serializable object Register @Serializable data class Nickname(val id: String? = null) @Serializable data class Home(val id: String? = null) @Serializable object HomeCookbooks @Serializable object HomeCooking @Serializable object HomeSearch [/code]