【问题标题】:Passing variables to Kotlin Coroutine in Android在 Android 中将变量传递给 Kotlin 协程
【发布时间】:2020-06-26 16:00:11
【问题描述】:

我有一个片段、视图模型和数据库。我从删除的片段中在 viewModel 中调用此方法 通过 id 列表从数据库中获取数据。

    fun deleteDefects(idList: List<Long>) {
        Log.d("RoundViewModel", idList.toString())
        viewModelScope.launch(Dispatchers.IO) {
            Log.d("RoundViewModel", idList.toString())
            ddb.dao().delAddedDefect(idList)
        }
    }

它有效.. 有时,10 次中有 2 到 3 次会删除数据。有时 idList 启动时为空。

2020-06-26 18:40:44.461 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [259, 260]
2020-06-26 18:40:44.464 18524-18555/ru.debaser.projects.inspectionsheet D/RoundViewModel: []
2020-06-26 18:40:47.453 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [264, 267]
2020-06-26 18:40:47.457 18524-18555/ru.debaser.projects.inspectionsheet D/RoundViewModel: []
2020-06-26 18:40:50.838 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [276, 267]
2020-06-26 18:40:50.841 18524-18555/ru.debaser.projects.inspectionsheet D/RoundViewModel: []
2020-06-26 18:40:53.896 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [276, 267, 264]
2020-06-26 18:40:53.899 18524-18555/ru.debaser.projects.inspectionsheet D/RoundViewModel: []
2020-06-26 18:40:56.947 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [259, 260, 264]
2020-06-26 18:40:56.950 18524-18555/ru.debaser.projects.inspectionsheet D/RoundViewModel: []
2020-06-26 18:41:00.023 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [264, 265, 267]
2020-06-26 18:41:00.027 18524-18554/ru.debaser.projects.inspectionsheet D/RoundViewModel: []
2020-06-26 18:41:02.731 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [264, 265]
2020-06-26 18:41:02.733 18524-18554/ru.debaser.projects.inspectionsheet D/RoundViewModel: []
2020-06-26 18:41:08.200 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [277, 267]
2020-06-26 18:41:08.201 18524-18554/ru.debaser.projects.inspectionsheet D/RoundViewModel: []
2020-06-26 18:41:11.694 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [264, 259]
2020-06-26 18:41:11.695 18524-18554/ru.debaser.projects.inspectionsheet D/RoundViewModel: [264, 259]
2020-06-26 18:41:19.528 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [265, 267]
2020-06-26 18:41:19.530 18524-18591/ru.debaser.projects.inspectionsheet D/RoundViewModel: []
2020-06-26 18:41:23.780 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [276, 267]
2020-06-26 18:41:23.782 18524-18556/ru.debaser.projects.inspectionsheet D/RoundViewModel: [276, 267]

【问题讨论】:

    标签: android kotlin kotlin-coroutines


    【解决方案1】:

    您拥有的代码应该可以正常工作,但看起来您在调用 deleteDefects 时正在做一些顽皮的事情。

    List&lt;...&gt; 是只读接口,不保证不变性。 我想您在将 idList 传递给函数后正在修改它。 像这样的...

    val idList = mutableListOf<Long>()
    idList.add(50)
    idList.add(20)
    
    deleteDefects(idList)
    idList.clear()
    

    这是一个竞争条件!由于deleteDefects 中引入了并发性,因此在传入idList 后,您不应该触摸它......永远。除非你使用锁或类似的东西。

    一个快速的解决方法是制作一个防御性副本,就像这样。

    fun deleteDefects(idListTmp: List<Long>) {
        val idList = idListTmp.toList() // Safe!
        Log.d("RoundViewModel", idList.toString())
        viewModelScope.launch(Dispatchers.IO) {
            Log.d("RoundViewModel", idList.toString())
            ddb.dao().delAddedDefect(idList)
        }
    }
    

    正确的解决方法是在调用 deleteDefacts(idList) 后不修改 idList

    另一个适当的解决方法可能是只做deleteDefacts(idList.toList())

    【讨论】:

    • 谢谢,它有效。我将包含来自适配器 vm.deleteDefects(addedDefectAdapter.selectedItems) 的 selectedItems 的变量传递给 deleteDefects 现在我添加了 toList() vm.deleteDefects(addedDefectAdapter.selectedItems.toList()) 并且一切都按我的预期工作。
    【解决方案2】:

    调用者(函数deleteDefects)中的线程不会等到被调用者完成(有时)。 要对其进行测试,请将其包装在 runBlocking 中。

    建议:使用 await 或 join。

    这个article 可以帮助你弄清楚。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-18
      • 1970-01-01
      • 1970-01-01
      • 2016-07-14
      • 1970-01-01
      • 2021-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多