首页 > 解决方案 > Kotlin协程不下载数据

问题描述

我在我的 Android 项目中使用 Kotlin corountines。我正在尝试下载一些数据并在文本视图中显示。

以下是我的代码

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        tv.setOnClickListener {
            downloadData()
        }
    }


    private fun downloadData() {

        runBlocking {
            pb_activity_main.visibility = View.VISIBLE
            var data = ""
            async {
                data = downloadDataBlocking()
            }.await()
            tv.text = data
            pb_activity_main.visibility = View.GONE

        }
    }


    private fun downloadDataBlocking(): String {
        val client = OkHttpClient()
        val request = Request.Builder().url("https://jsonplaceholder.typicode.com/posts").build()
        val response = client.newCall(request).execute()
        return response.body()?.string() ?: ""
    }
}

但是没有下载数据。我不知道为什么。

我已经在清单中包含了互联网许可,并且网址也可以使用。

标签: androidkotlinkotlinx.coroutines

解决方案


试试这个:

class MainActivity : AppCompatActivity(), CoroutineScope {

    private val job = Job()
    override val coroutineContext = Dispatchers.Main + job

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        tv.setOnClickListener {
            downloadData()
        }
    }


    private fun downloadData() {
        launch {
            pb_activity_main.visibility = View.VISIBLE
            tv.text = withContext(Dispatchers.IO) { downloadDataBlocking() }
            pb_activity_main.visibility = View.GONE
        }
    }


    private fun downloadDataBlocking(): String {
        val client = OkHttpClient()
        val request = Request.Builder().url("https://jsonplaceholder.typicode.com/posts").build()
        val response = client.newCall(request).execute()
        return response.body()?.string() ?: ""
    }
}

第一:你不应该使用runBLocking超出单元测试或其他特殊领域。

不应从协程中使用此功能。它旨在将常规阻塞代码连接到以挂起样式编写的库,以用于主要功能和测试。

第二:

协程总是与应用程序中的某个局部范围相关,这是一个生命周期有限的实体,如 UI 元素

这就是为什么Activity实现CoroutineScope. 老实说,一个更好的地方是ViewModelor Presenter,但我在代码中看不到任何东西......

async第三,在定义之后使用它是毫无意义await的。那就用withContext吧。


推荐阅读