【问题标题】:Unable to retrive data from database using Room and coroutine无法使用 Room 和协程从数据库中检索数据
【发布时间】:2020-09-28 06:41:42
【问题描述】:

我无法检索数据。 有什么方法可以访问我们的数据库,我们可以检查到目前为止我们插入的内容。
在这段代码中,我试图插入我在计算器中所做的最新计算以及我的交易数量。使用协程、房间和视图模型。

    import android.app.Application
    import androidx.lifecycle.AndroidViewModel
    import androidx.lifecycle.LiveData
    import androidx.lifecycle.MutableLiveData
    import androidx.navigation.NavController
    import com.kotlin_developer.calculator.database.CalculationDatabaseDao
    import com.kotlin_developer.calculator.database.CalculatorHistory
    import kotlinx.coroutines.*
    import timber.log.Timber

    class CalculatorViewModel(
        val
        database: CalculationDatabaseDao,
        application: Application
    ) : AndroidViewModel(application) {

        var operatorEnabled: Boolean = false
        var firstResult: Double = 0.0
        var operator: Char = ' '
        var ifNumeric: Boolean = true
        var secondResultLenght = 0

        //    First step of coroutines is to create job, this can cancel all the coroutines started by this view model
        private var viewModelJob = Job()

        //    Second step is to create the scope where we want to run our code
        // Scope determines what thread the coroutines will run on, it also needs to know about the job
        private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)

    //    private val history = database.getAllCalculation()

        private var _totalTransaction = MutableLiveData<Int>()
        val totalTransaction: LiveData<Int>
            get() = _totalTransaction

        //Getting currentCalculation
        private var _currentCalculation = MutableLiveData<String>()
        val currentCalculation: LiveData<String>
            get() = _currentCalculation

        //Getting current result
        private var _currentResult = MutableLiveData<String>()
        val currentResult: LiveData<String>
            get() = _currentResult

        val navControler = MutableLiveData<NavController>()

        private val _secondResult = MutableLiveData<Double>()
        val secondResult: LiveData<Double>
            get() = _secondResult

        private var _resultTextValue = MutableLiveData<Double>()
        val resultTextValue: LiveData<Double>
            get() = _resultTextValue

        private var _lastHistory = MutableLiveData<CalculatorHistory>()
        val lastHistory: LiveData<CalculatorHistory>
            get() = _lastHistory

        val totalCalculation = mutableListOf<String>()

        init {
            Timber.i("Calculator View Model created")
            _resultTextValue.value = 0.0
            _secondResult.value = 0.0
            _totalTransaction.value = 0
        }

        fun insertData() {
            uiScope.launch {
                val newHistory = CalculatorHistory(
                    totalTransaction.value?.toLong()!!,
                    totalCalculation[totalTransaction.value!! - 1]
                )
                insert(newHistory)
            }
        }

        private suspend fun insert(newHistory: CalculatorHistory) {
            withContext(Dispatchers.IO) {
                database.insert(newHistory)
                Timber.i("Data Inserted")
            }
        }

        internal fun initializeHistory() {
            uiScope.launch {
                _lastHistory.value = getHistoryFromDatabase()
            }
            Timber.i("${lastHistory.value?.transactionNumber} and ${lastHistory.value?.calculation}")
        }

        private suspend fun getHistoryFromDatabase(): CalculatorHistory? {
            return withContext(Dispatchers.IO) {
                var lastCalculation = database.get(1)
                lastCalculation
            }
            Timber.i("${lastHistory.value?.transactionNumber} and ${lastHistory.value?.calculation}")
        }

        fun calculator(operator: Char): Double {
            return when (operator) {
                '+' -> firstResult.plus(secondResult.value ?: 0.0)
                '-' -> firstResult.minus(secondResult.value ?: 0.0)
                '*' -> firstResult.times(secondResult.value ?: 1.0)
                '/' -> firstResult.div(secondResult.value ?: 1.0)
                else -> firstResult.rem(secondResult.value ?: 1.0)
            }
        }

        fun createCalculation() {
            ifNumeric = false
            operatorEnabled = false
            _resultTextValue.value = calculator(operator)

            //This we can use in future to create a list of calculation
            totalCalculation.add(
                totalTransaction.value!!,
                "${currentCalculation.value}=${_resultTextValue.value}"
            )
            _currentResult.value = totalCalculation[totalTransaction.value!!]

            insertData()

            firstResult = _resultTextValue.value ?: 0.0
            _totalTransaction.value = _totalTransaction.value?.plus(1)
            _secondResult.value = 0.0
            secondResultLenght = 0
        }

        fun seprateNumber(number: Double) {
            if (operatorEnabled) {
                if (ifNumeric) {
                    _secondResult.value = number + (secondResult.value?.times(10.0))!!
                } else {
                    _secondResult.value = number
                }
            } else {
                firstResult = number + (firstResult * 10)
            }
        }

        fun clearText() {
            _resultTextValue.value = 0.0
            _currentResult.value = ""
            firstResult = 0.0
            _secondResult.value = 0.0
            secondResultLenght = 0
            operator = ' '
            operatorEnabled = false
            ifNumeric = false
            _currentCalculation.value = ""
        }

        fun ifSeprateNumber(number: Double) {
            seprateNumber(number)
            if (operatorEnabled) {
                secondCalculationText()
            } else {
                _currentCalculation.value = firstResult.toString()
            }
            ifNumeric = true
        }

        fun secondCalculationText() {
            _currentCalculation.value = _currentCalculation.value
                ?.removeRange(
                    _currentCalculation.value!!.length -
                            secondResultLenght, _currentCalculation.value!!.length
                )

            _currentCalculation.value =
                "${_currentCalculation.value}${secondResult.value.toString()}"
            secondResultLenght = secondResult.value.toString().length
            ifNumeric = true
        }

        fun addTextToField() {
            ifNumeric = false
            operatorEnabled = true
            _currentCalculation.value = "${_currentCalculation.value}${operator}"
        }


        override fun onCleared() {
            super.onCleared()
            //This cancels all the coroutines when the view model is getting closed
            viewModelJob.cancel()
            Timber.i("Calculator ViewModel destroyed")
        }
    }

【问题讨论】:

  • 不要创建自己的范围和工作,而是使用 android 提供的viewModelScope。并在DAO接口中使用suspend关键字,而不是手动调度到Dispatchers.IO,从而清理代码然后编辑问题并提问。

标签: android kotlin android-room kotlin-coroutines


【解决方案1】:

我认为您在 ViewModel 中做的事情太多了。如果您想查看数据库中的数据是什么,您应该有一个活动(视图,创建、更新和处理 UI 事件的活动)来观察视图模型中的实时数据。每次您将值插入数据库时​​,无论花费多少时间,一旦完成,它将触发对观察者的回调,您将获得新值。我将从这个开始,这样您就可以跟踪您在数据库中插入的内容,这是使用这些值的起点。

从您的视图/活动中会是这样的:

        yourViewModel.variableYouWant.observe(this, Observer { yourValue ->
           //do something with yourValue 
           })

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-27
    • 1970-01-01
    • 1970-01-01
    • 2014-04-20
    相关资源
    最近更新 更多