При использовании Android Navigation Compose возникла проблема с сохраненными аргументами навигации.
Например, у меня есть следующие маршруты:
@Serializable
object ScreenA
@Serializable
data class ScreenB(val id: Long? = null)
@Serializable
object ScreenC
Сначала я перехожу от ScreenA к ScreenB с параметром и открываю ComposableScreenB:
...
navController.navigate(ScreenB(3L))
...
composable { backStackEntry ->
ComposableScreenB(
id: () -> Long? = { backStackEntry.savedStateHandle.toRoute().id }
)
}
Я использую значение параметра для инициирования более сложного внутреннего изменяемого состояния ComposableScreenB, и тогда значение параметра навигации не требуется. Если id == null, то ComposableScreenB использует внутреннюю константу (которую ScreenA не знает) для первой инициализации и ничего не делает, если инициализация уже произошла. Кроме того, id может использоваться для повторной инициализации ScreenB (например, из глубокой ссылки), поэтому я не могу полностью игнорировать параметр, если ComposableScreenB инициализирован.
Но после перехода к ScreenC и перехода к ScreenB с помощью navController.popBackStack(inclusive = true) параметр id снова имеет значение 3L, полученный при запуске от ScreenA и ComposableScreenB, повторно инициализируется этим идентификатором.
Как избежать сохранения старого параметра навигации?
Минимальный воспроизводимый пример
MainActivity.kt:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
Box(Modifier.safeDrawingPadding()) {
MainScreen()
}
}
}
}
MainScreen.kt:
@Serializable
object ScreenA
@Serializable
data class ScreenB(val id: Long? = null)
@Serializable
object ScreenC
@Composable
fun MainScreen() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = ScreenA
) {
composable {
ComposableScreenA(
navigateToB = remember(navController) { { id ->
// pass initial id to ScreenB
navController.navigate(ScreenB(id)) {
// forget about ScreenA
popUpTo(ScreenA) {
inclusive = true
}
}
} }
)
}
composable(
// possible reinitialization of ComposableScreenB
deepLinks = listOf(
navDeepLink(basePath = "example://navigation/screenB")
)
) { navStackEntry ->
// read input parameter
val id = navStackEntry.toRoute().id
ComposableScreenB(
id = { id },
navigateToC = remember(navController) { {
navController.navigate(ScreenC)
} }
)
}
composable {
Column {
Text("Some information")
Button(
onClick = remember(navController) { {
navController.popBackStack(inclusive = true)
} }
) {
Text("Back")
}
}
}
}
}
@Composable
fun ComposableScreenB(
id: () -> Long?,
navigateToC: () -> Unit
) {
// internal function for read complex data from external storage
fun getComplexData(id: Long?): ComplexData = ComplexData(id ?: 2, "id=${id ?: 2}")
// prepare internal complex data state
var complexDataState by remember { mutableStateOf(getComplexData(id())) }
Column {
// label to show selected complex data
Text(text = complexDataState.toString())
// change complex data on label
ComplexDataChanger(
changeData = { complexDataState = getComplexData(it) }
)
// navigate next ScreenC
Button(onClick = navigateToC) {
Text("Navigate to ScreenC")
}
}
}
@Composable
fun ComposableScreenA(
navigateToB: (Long?) -> Unit
) {
Column {
var initialId by remember { mutableStateOf("") }
TextField(
value = initialId,
onValueChange = { initialId = it },
label = { Text("Enter initial id") }
)
Button(
onClick = {
navigateToB(
if (initialId.isEmpty() || initialId.contains(Regex("[^0-9]"))) {
null
} else {
initialId.toLong()
}
)
}
) {
Text("Confirm initial id")
}
}
}
@Composable
fun ComplexDataChanger(
changeData: (Long) -> Unit
) {
// internal changes of complex data state
var complexDataId by remember { mutableStateOf("2") }
TextField(
value = complexDataId,
onValueChange = { complexDataId = it },
label = { Text("Enter complex data id") }
)
Button(
enabled = complexDataId.isNotEmpty() && !complexDataId.contains(Regex("[^0-9]+")),
onClick = { changeData(complexDataId.toLong()) }
) {
Text("Change complex data")
}
}
data class ComplexData(val id: Long, val name: String)
Подробнее здесь: https://stackoverflow.com/questions/798 ... nnecessary
Аргументы навигации Android Compose сохранены ненужными ⇐ Android
Форум для тех, кто программирует под Android
-
Anonymous
1766067298
Anonymous
При использовании Android Navigation Compose возникла проблема с сохраненными аргументами навигации.
Например, у меня есть следующие маршруты:
@Serializable
object ScreenA
@Serializable
data class ScreenB(val id: Long? = null)
@Serializable
object ScreenC
Сначала я перехожу от ScreenA к ScreenB с параметром и открываю ComposableScreenB:
...
navController.navigate(ScreenB(3L))
...
composable { backStackEntry ->
ComposableScreenB(
id: () -> Long? = { backStackEntry.savedStateHandle.toRoute().id }
)
}
Я использую значение параметра для инициирования более сложного внутреннего изменяемого состояния ComposableScreenB, и тогда значение параметра навигации не требуется. Если id == null, то ComposableScreenB использует внутреннюю константу (которую ScreenA не знает) для первой инициализации и ничего не делает, если инициализация уже произошла. Кроме того, id может использоваться для повторной инициализации ScreenB (например, из глубокой ссылки), поэтому я не могу полностью игнорировать параметр, если ComposableScreenB инициализирован.
Но после перехода к ScreenC и перехода к ScreenB с помощью navController.popBackStack(inclusive = true) параметр id снова имеет значение 3L, полученный при запуске от ScreenA и ComposableScreenB, повторно инициализируется этим идентификатором.
Как избежать сохранения старого параметра навигации?
[b]Минимальный воспроизводимый пример[/b]
MainActivity.kt:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
Box(Modifier.safeDrawingPadding()) {
MainScreen()
}
}
}
}
MainScreen.kt:
@Serializable
object ScreenA
@Serializable
data class ScreenB(val id: Long? = null)
@Serializable
object ScreenC
@Composable
fun MainScreen() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = ScreenA
) {
composable {
ComposableScreenA(
navigateToB = remember(navController) { { id ->
// pass initial id to ScreenB
navController.navigate(ScreenB(id)) {
// forget about ScreenA
popUpTo(ScreenA) {
inclusive = true
}
}
} }
)
}
composable(
// possible reinitialization of ComposableScreenB
deepLinks = listOf(
navDeepLink(basePath = "example://navigation/screenB")
)
) { navStackEntry ->
// read input parameter
val id = navStackEntry.toRoute().id
ComposableScreenB(
id = { id },
navigateToC = remember(navController) { {
navController.navigate(ScreenC)
} }
)
}
composable {
Column {
Text("Some information")
Button(
onClick = remember(navController) { {
navController.popBackStack(inclusive = true)
} }
) {
Text("Back")
}
}
}
}
}
@Composable
fun ComposableScreenB(
id: () -> Long?,
navigateToC: () -> Unit
) {
// internal function for read complex data from external storage
fun getComplexData(id: Long?): ComplexData = ComplexData(id ?: 2, "id=${id ?: 2}")
// prepare internal complex data state
var complexDataState by remember { mutableStateOf(getComplexData(id())) }
Column {
// label to show selected complex data
Text(text = complexDataState.toString())
// change complex data on label
ComplexDataChanger(
changeData = { complexDataState = getComplexData(it) }
)
// navigate next ScreenC
Button(onClick = navigateToC) {
Text("Navigate to ScreenC")
}
}
}
@Composable
fun ComposableScreenA(
navigateToB: (Long?) -> Unit
) {
Column {
var initialId by remember { mutableStateOf("") }
TextField(
value = initialId,
onValueChange = { initialId = it },
label = { Text("Enter initial id") }
)
Button(
onClick = {
navigateToB(
if (initialId.isEmpty() || initialId.contains(Regex("[^0-9]"))) {
null
} else {
initialId.toLong()
}
)
}
) {
Text("Confirm initial id")
}
}
}
@Composable
fun ComplexDataChanger(
changeData: (Long) -> Unit
) {
// internal changes of complex data state
var complexDataId by remember { mutableStateOf("2") }
TextField(
value = complexDataId,
onValueChange = { complexDataId = it },
label = { Text("Enter complex data id") }
)
Button(
enabled = complexDataId.isNotEmpty() && !complexDataId.contains(Regex("[^0-9]+")),
onClick = { changeData(complexDataId.toLong()) }
) {
Text("Change complex data")
}
}
data class ComplexData(val id: Long, val name: String)
Подробнее здесь: [url]https://stackoverflow.com/questions/79849725/android-compose-navigation-arguments-saved-unnecessary[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия