kotlin - 首次运行时未定义的迭代器值

标签 kotlin concurrency android-room kotlin-coroutines

onViewCreated()内的MythFragment中,执行以下步骤。

  • 预填充Room数据库。
  • 从数据库中提取所有记录到MutableLiveData<List<..>>
  • 初始化这些数据的迭代器
  • 单击“下一步”按钮检查条件it.hasNext() == true

  • 由于某种原因,仅在程序的第一次运行中,it.hasNext()才给我false。我希望它是正确的,因为步骤1-3应该已经确保,列表已填充,并且迭代器指向第一个元素。
    有趣的是,以后在MythView上进行的任何导航都可以正确检索元素,并且it.hasNext()给我trueMythFragment.kt
    class MythFragment : Fragment() {
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
    
            viewModel = ViewModelProviders.of(this).get(MythViewModel::class.java)
            viewModel.populateMyths()
            viewModel.fetchFromDatabase()
    
            buttonNextMyth.setOnClickListener {
                mythEvaluation.visibility = View.GONE
                buttonIsThisMythTruthful.visibility = View.VISIBLE
    
                viewModel.mythsIterator.let {
                    if (it.hasNext()) {
                        val myth = it.next()
                        mythText.text = myth.myth
                        mythEvaluation.text = myth.evaluation
                    } else {
                        Toast.makeText(activity, "There is no myth, because it.hasNext() is false!)", Toast.LENGTH_SHORT).show()
                        val action = MythFragmentDirections.actionMenuFragment()
                        Navigation.findNavController(view).navigate(action)
                    }
                }
            }
        }
    }
    
    MythViewModel.kt
    class MythViewModel(application: Application) : BaseViewModel(application) {
    
        private val myths = MutableLiveData<List<Myth>>()
        lateinit var mythsIterator: Iterator<Myth>
    
        fun populateMyths() {
            launch {
                val dao = MythDatabase(getApplication()).mythDao()
    
                if (dao.getRowCount() > 0)
                    return@launch
    
                val mythList = arrayListOf(
                    Myth("This is the myth 1", "This is the evaluation of the myth 1"),
                    Myth("This is the myth 2", "This is the evaluation of the myth 2"),
                    Myth("This is the myth 3", "This is the evaluation of the myth 3"),
                    Myth("This is the myth 4", "This is the evaluation of the myth 4"),
                    Myth("This is the myth 5", "This is the evaluation of the myth 5")
                )
    
                dao.insertAll(
                    *mythList.toTypedArray()
                )
            }
        }
    
        fun fetchFromDatabase() {
            launch {
                val mythList = MythDatabase(getApplication()).mythDao().getAllMyths()
                myths.value = mythList
                myths.value?.let {
                    mythsIterator = it.iterator()
                }
            }
        }
    }
    
    我相信问题可能出在并发(协程)上,但是我不明白我在做什么错。

    最佳答案

    当函数populateMyths()fetchFromDatabase()都启动新的协程时,这两个协程将并行运行。因此,第一次调用fetchFromDatabase()时,可能是在dao.insertAll()中发生populateMyths()之前检索数据。
    也许您应该重新思考/阐明通过启动这些协同程序要完成的目标。

    关于kotlin - 首次运行时未定义的迭代器值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62866261/

    相关文章:

    java - 在 sun.misc.Unsafe.park 等待( native 方法)

    java - Hashmap 并发问题

    java - 如何创建容量受限的队列实现?

    android - 当在房间数据库中添加新表时,从版本 1 到版本 2

    android - 为什么编译器找不到 android.R.id.home 常量?

    android - 如果只是项目的内容发生变化,PagedListAdapter 不会更新列表

    java - 如何启动本地库的annotationProcessing(kapt)?

    Android Studio 在第二次构建后显示 Kotlin 依赖警告

    java - Android:使用 Room 和 Firestore?

    android - 使用 Room 实时查询进行生命周期状态管理