Логическое состояние в компоновке изменяется до того, как переменная, которую я помещаю после ее назначения
Итак, у меня есть две ViewModels в моем приложении Calculator, на которые я все ссылаюсь в своем Compose NavGraph, поэтому я могу использовать один и тот же экземпляр ViewModel. Я установил логическое состояние (historyCheck) в первой ViewModel, и я установил его слишком истинным, чтобы «Очистить» историю, которую я установил, которая является историей вычислений, которые я пытаюсь получить из обеих ViewModels. Теперь проблема заключается в том, что логическое состояние «strCalcViewModel.historyCheck» изменяется до того, как переменная над ним будет назначена, что затем приведет к сбою оператора «if», который я установил, что, в свою очередь, приведет к сбою всей реализации, поскольку он всегда установлен на false.
Это мой код ниже... Мой Compose NavGraph.
@Composable
fun ComposeNavigation(
navController: NavHostController,
) {
/**
* Here We declare an Instance of our Two ViewModels, their states and History States. This is because we don't want to have the same States for the two Screens.
*/
val strCalcViewModel = viewModel<CalculatorViewModel>()
val sciCalcViewModel = viewModel<ScientificCalculatorViewModel>()
val strCalcState = strCalcViewModel.strState
val sciCalcState = sciCalcViewModel.sciState
val strHistoryState = strCalcViewModel.historyState
val sciHistoryState = sciCalcViewModel.historyState
// This holds our current available 'HistoryState' based on where the Calculation was performed(Screens) by the USER.
var currHistory by remember { mutableStateOf(CalculatorHistoryState()) }
if(strCalcViewModel.historyCheck) {
currHistory = strHistoryState
strCalcViewModel.historyCheck = false // this gets assigned before the 'currHistory' variable above thereBy making the the if to always be false
} else {
currHistory = sciHistoryState
}
NavHost(
navController = navController,
startDestination = "main_screen",
) {
composable("main_screen") {
MainScreen(
navController = navController, state = strCalcState, viewModel = strCalcViewModel
)
}
composable("first_screen") {
FirstScreen(
navController = navController, state = sciCalcState, viewModel = sciCalcViewModel
)
}
composable("second_screen") {
SecondScreen(
navController = navController, historyState = currHistory, viewModel = strCalcViewModel
)
}
}
}
Тогда моя ViewModel
private const val TAG = "CalculatorViewModel"
class CalculatorViewModel : ViewModel() {
var strState by mutableStateOf(CalculatorState())
// This makes our state accessible by outside classes but still readable
private set
var historyState by mutableStateOf(CalculatorHistoryState())
private set
private var leftBracket by mutableStateOf(true)
private var check = 0
var checkState by mutableStateOf(false)
var historyCheck by mutableStateOf(false)
// Function to Register our Click events
fun onAction(action : CalculatorAction) {
when(action) {
is CalculatorAction.Number -> enterNumber(action.number)
is CalculatorAction.Decimal -> enterDecimal()
is CalculatorAction.Clear -> {
strState = CalculatorState()
check = 0
}
is CalculatorAction.ClearHistory -> checkState = true
is CalculatorAction.Operation -> enterStandardOperations(action.operation)
is CalculatorAction.Calculate -> performStandardCalculations()
is CalculatorAction.Delete -> performDeletion()
is CalculatorAction.Brackets -> enterBrackets()
}
}
// We are Basically making the click events possible by modifying the 'state'
private fun performStandardCalculations() {
val primaryStateChar = strState.primaryTextState.last()
val primaryState = strState.primaryTextState
val secondaryState = strState.secondaryTextState
if (!(primaryStateChar == '(' || primaryStateChar == '%')) {
strState = strState.copy(
primaryTextState = secondaryState
)
strState = strState.copy(secondaryTextState = "")
// Below, we store our Calculated Values in the History Screen after it has been Calculated by the USER.
historyState = historyState.copy(
historySecondaryState = secondaryState
)
historyState = historyState.copy(
historyPrimaryState = primaryState
)
historyCheck = true // this is where I assign it to true when I complete my Calculations and pass it to the history State
} else {
strState = strState.copy(
secondaryTextState = "Format error"
)
strState = strState.copy(
color = ferrari
)
}
}
}
2 ответа
Вы проверяете условие if и присваиваете новое значение переменной viewModel в функции Compose, это неправильно! вы должны использовать побочные эффекты
LaunchedEffect(strCalcViewModel.historyCheck) {
if(strCalcViewModel.historyCheck) {
currHistory = strHistoryState
strCalcViewModel.historyCheck = false
} else {
currHistory = sciHistoryState
}}
Всякий раз, когда происходит новое изменение вstrCalcViewModel.historyCheck
этот блок будет работать, вы можете проверить здесь для получения дополнительной информации Побочные эффекты в Compose
Основываясь на ответе Sadegh.t, я заработал, но не написал его точно так же и использовал другую реализацию, которую я опубликую сейчас.
Я по-прежнему использовал побочный эффект, но вместо проверки изменений в «historyCheck» я проверял изменения в самом «состоянии», а также вместо использования логической переменной я использовал само состояние в качестве основы для проверки. Состояние. Итак, вот мой ответ, основанный на оригинальном ответе Sadegh.t.
var currHistory by remember { mutableStateOf(CalculatorHistoryState()) }
LaunchedEffect(key1 = strCalcState) {
if(strCalcState.secondaryTextState.isEmpty()) {
currHistory = strHistoryState
}
}
LaunchedEffect(key1 = sciCalcState) {
if(sciCalcState.secondaryTextState.isEmpty()) {
currHistory = sciHistoryState
}
}