Eu tenho um aplicativo muito simples:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyTheme {
Navigation(
navController = rememberNavController()
)
}
}
}
}
Com duas telas:
sealed class Screen(val route: String){
data object MainScreen : Screen("main_screen")
data object DetailScreen : Screen("detail_screen")
fun withArgs(vararg args: String) = buildString {
append(route)
args.forEach { arg ->
append("/$arg")
}
}
}
O que eu quero é passar um texto de uma tela para outra usando navegação:
@Composable
fun Navigation(
navController: NavHostController
) {
NavHost(
navController = navController,
startDestination = MainScreen.route
) {
composable(
route = MainScreen.route
) {
MainScreen(
navigateToDetailScreen = { text ->
navController.navigate(DetailScreen.withArgs(text))
}
)
}
composable(
route = DetailScreen.route + "/{text}",
arguments = listOf(
navArgument("text") {
type = NavType.StringType
}
)
) { entry ->
DetailScreen(
text = entry.arguments?.getString("text")!!
)
}
}
}
E aqui estão minhas duas telas:
@Composable
fun MainScreen(
navigateToDetailScreen: (text: String) -> Unit
) {
Log.d("MyTag", "MainScreen")
var text by remember { mutableStateOf("") }
Column(
modifier = Modifier.fillMaxSize()
) {
TextField(
value = text,
onValueChange = {
text = it
}
)
Button(
onClick = {
navigateToDetailScreen(text)
}
) {
Text(
text = "Navigate"
)
}
}
}
@Composable
fun DetailScreen(text: String) {
Log.d("MyTag", "DetailScreen")
Column(
modifier = Modifier.fillMaxSize()
) {
Text(
text = text
)
}
}
Os dois problemas que estou enfrentando são:
Cada vez que escrevo um novo personagem dentro do
TextField
, aMainScreen
diversão dispara continuamente.Quando pressiono
Navigate
, aMainScreen
diversão dispara novamente,DetailScreen
dispara uma vez e aMainScreen
diversão dispara novamente, resultando na exibição:MainScreen //when the app starts MainScreen //when adding the first character MainScreen //when adding the second character MainScreen //when clicking the "Navigate" button DetailScreen //when the second screen is displayed MainScreen //For no reason
Como impedir que isso aconteça?
A recomposição não significa necessariamente que a UI mudou; é apenas uma solicitação para reavaliar o elemento que pode ser composto para ver se algo precisa ser atualizado. Nem todas as recomposições resultam em atualizações reais da IU. Às vezes, as recomposições são acionadas, mas depois descartadas devido a alguma otimização
Por isso, se você colocar uma declaração de log diretamente dentro do seu composable, ela será executada toda vez que o composable for recomposto. Isso pode levar a um grande número de entradas de log, o que pode fazer parecer que sua UI está sendo reconstruída ou recriada várias vezes, mesmo que não seja esse o caso.
Prefira usar
LaunchedEffect
ouSideEffect