【问题标题】:Kotlin: lag in coroutine runBlockingKotlin:协程运行阻塞中的滞后
【发布时间】:2020-03-26 12:05:09
【问题描述】:

我正在使用 kotlin Coroutines 执行异步网络操作以避免NetworkOnMainThreadException。 问题是我使用runBlocking 时发生的延迟,这需要一些时间才能完成当前线程。

我怎样才能防止这种延迟或滞后,并允许异步操作无延迟地完成

    runBlocking {
        val job = async (Dispatchers.IO) {
        try{
        //Network operations are here
        }catch(){

        }

     }

 }

【问题讨论】:

    标签: android kotlin delay coroutine


    【解决方案1】:

    通过使用runBlocking,您将阻塞主线程,直到协程完成。

    NetworkOnMainThread 异常不会被抛出,因为从技术上讲,请求是在后台线程上完成的,但是通过让主线程等到后台线程完成,这同样糟糕!

    要解决这个问题,你可以launch 一个协程,任何依赖于网络请求的代码都可以在协程内完成。这样代码仍然可以在主线程上执行,但不会阻塞。

    // put this scope in your activity or fragment so you can cancel it in onDestroy()      
    val scope = MainScope() 
    
    // launch coroutine within scope
    scope.launch(Dispachers.Main) {
        try {
            val result = withContext(Dispachters.IO) {
                // do blocking networking on IO thread
                ""
            }
            // now back on the main thread and we can use 'result'. But it never blocked!
        } catch(e: Exception) {
        }
    }
    

    如果你不关心结果,只想在不同的线程上运行一些代码,这可以简化为:

    GlobalScope.launch(Dispatchers.IO) {
        try {
            // code on io thread
        } catch(e: Exception) {
        }
    }
    

    注意:如果您使用的是封闭类中的变量或方法,您仍应使用自己的范围,以便及时取消。

    【讨论】:

    • 谢谢,但是使用第一个解决方案,我无法返回结果以在范围外使用它,我如何提取范围外的数据以使用它?(在我的示例中,我使用它附加到列表适配器)
    • 你不要把它移到协程之外。在它说“// 现在回到主线程”的地方,您可以访问结果和外部范围。因此,您可以在此处更新适配器或导航
    • 当我放在你提到的同一个地方时: val myListAdapter = InvestListAdapter(this,arg1,arg2,arg3) 它给出了以下错误: 1-未解析的 arg1、arg2、arg3 参考(所有这些在范围内)2-this:类型不匹配
    • 您有名为 arg1、arg2 和 arg3 的变量?对于类型不匹配:“this”现在指向协程对象,但您可以使用 this@MainActivity 或您所在的任何类来获取“this”引用。除此之外,您的问题不再与协程有关,因此您可以使用您的实际代码发布一个新问题
    猜你喜欢
    • 1970-01-01
    • 2020-01-04
    • 2020-05-21
    • 1970-01-01
    • 1970-01-01
    • 2020-11-04
    • 2022-12-12
    • 2018-12-29
    • 1970-01-01
    相关资源
    最近更新 更多