Логическое состояние в компоновке изменяется до того, как переменная, которую я помещаю после ее назначения

Итак, у меня есть две 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
    }
}
Другие вопросы по тегам