我在Android项目中使用Kotlin协同体。我正在尝试下载一些数据并在textview中显示。
以下是我的代码
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() ?: ""
}
}
但是没有下载数据。我不知道为什么。
我已在Manifest中添加了Internet许可,并且该网址也可以正常工作。
答案 0 :(得分:2)
尝试一下:
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
。
This function不应在协程中使用。它旨在将常规的阻塞代码桥接到以挂起方式编写的库中,以用于主要功能和测试中。
第二:
Coroutines are always related to some local scope in your application,这是寿命有限的实体,like a UI element。
这就是Activity
实现CoroutineScope
的原因。老实说,更合适的地方是ViewModel
或Presenter
,但是我在代码中看不到任何东西...
第三,在定义后立即使用async
和await
是毫无意义的。只需使用withContext
。