如何在 Android 中等待 khttp (kotlin) 响应
How to wait for khttp (kotlin) response in Android
我一直在尝试使用 khttp 在 android activity 中发送一个 .jpg 文件,但未能成功。
fun sendImage(view: View) {
try {
var bmp = (imageView?.drawable as BitmapDrawable).bitmap
var bos = ByteArrayOutputStream()
bmp.compress(Bitmap.CompressFormat.JPEG, 0, bos)
var response: Response? = null
findViewById<TextView>(R.id.image_desc).text = "Connecting to " + SERVER_URL;
try {
val job=GlobalScope.launch {
response = post(SERVER_URL, files = listOf(File(path).fileLike(name = "Image.jpg")))
}
findViewById<TextView>(R.id.image_desc).text = "Image contains: ${response?.text}"
} catch (e: Exception) {
findViewById<TextView>(R.id.image_desc).text = "Connection failed - please check fields are valid"
findViewById<TextView>(R.id.image_desc).text = e.toString()
}
} catch (e: UnknownHostException) {
findViewById<TextView>(R.id.image_desc).text = "Unknown host :("
e.printStackTrace()
} catch (e: IOException) {
findViewById<TextView>(R.id.image_desc).text = "IO exceptiion :("
e.printStackTrace()
} catch (e: Exception) {
findViewById<TextView>(R.id.image_desc).text = "Other exception :("
e.printStackTrace()
}
}
我一发送图像,image_desctextView 的文本更改为图像包含:null。我确定服务器不是问题,因为当我用这个 python 代码测试它时:
import requests
url=...
files = {'file': open('./test/cat.jpg', 'rb')}
r=requests.post(url,files=files)
print (r.text)
我在短暂的延迟后得到了想要的响应。我尝试将 sendImage 转换为挂起函数并编写 job.join() 但这会使应用程序崩溃。应该如何解决这个问题?
尝试下一个代码:
val job = GlobalScope.launch(Dispatchers.Main) {
val postOperation = async(Dispatchers.IO) { // <- extension on launch scope, launched in IO dispatcher
// blocking I/O operation
post(SERVER_URL, files = listOf(File(path).fileLike(name = "Image.jpg")))
}
response = postOperation.await() // wait for result of I/O operation without blocking the main thread
findViewById<TextView>(R.id.image_desc).text = "Image contains: ${response?.text}"
}
同时将下一行添加到应用程序的 build.gradle
依赖项中:
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'
注意 GlobalScope
不鼓励使用,启动协同程序使用 CoroutineScope
的实例,或像 viewModelScope
or lifecycleScope
这样的现有实例.
更新:
正确的方法是在 Activity
:
中使用 lifecycleScope
lifecycleScope.launch { // uses Dispatchers.Main context
val response = withContext(Dispatchers.IO) { // change context to background thread
// blocking I/O operation
post(SERVER_URL, files = listOf(File(path).fileLike(name = "Image.jpg")))
}
findViewById<TextView>(R.id.image_desc).text = "Image contains: ${response?.text}"
}
我一直在尝试使用 khttp 在 android activity 中发送一个 .jpg 文件,但未能成功。
fun sendImage(view: View) {
try {
var bmp = (imageView?.drawable as BitmapDrawable).bitmap
var bos = ByteArrayOutputStream()
bmp.compress(Bitmap.CompressFormat.JPEG, 0, bos)
var response: Response? = null
findViewById<TextView>(R.id.image_desc).text = "Connecting to " + SERVER_URL;
try {
val job=GlobalScope.launch {
response = post(SERVER_URL, files = listOf(File(path).fileLike(name = "Image.jpg")))
}
findViewById<TextView>(R.id.image_desc).text = "Image contains: ${response?.text}"
} catch (e: Exception) {
findViewById<TextView>(R.id.image_desc).text = "Connection failed - please check fields are valid"
findViewById<TextView>(R.id.image_desc).text = e.toString()
}
} catch (e: UnknownHostException) {
findViewById<TextView>(R.id.image_desc).text = "Unknown host :("
e.printStackTrace()
} catch (e: IOException) {
findViewById<TextView>(R.id.image_desc).text = "IO exceptiion :("
e.printStackTrace()
} catch (e: Exception) {
findViewById<TextView>(R.id.image_desc).text = "Other exception :("
e.printStackTrace()
}
}
我一发送图像,image_desctextView 的文本更改为图像包含:null。我确定服务器不是问题,因为当我用这个 python 代码测试它时:
import requests
url=...
files = {'file': open('./test/cat.jpg', 'rb')}
r=requests.post(url,files=files)
print (r.text)
我在短暂的延迟后得到了想要的响应。我尝试将 sendImage 转换为挂起函数并编写 job.join() 但这会使应用程序崩溃。应该如何解决这个问题?
尝试下一个代码:
val job = GlobalScope.launch(Dispatchers.Main) {
val postOperation = async(Dispatchers.IO) { // <- extension on launch scope, launched in IO dispatcher
// blocking I/O operation
post(SERVER_URL, files = listOf(File(path).fileLike(name = "Image.jpg")))
}
response = postOperation.await() // wait for result of I/O operation without blocking the main thread
findViewById<TextView>(R.id.image_desc).text = "Image contains: ${response?.text}"
}
同时将下一行添加到应用程序的 build.gradle
依赖项中:
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'
注意 GlobalScope
不鼓励使用,启动协同程序使用 CoroutineScope
的实例,或像 viewModelScope
or lifecycleScope
这样的现有实例.
更新:
正确的方法是在 Activity
:
lifecycleScope
lifecycleScope.launch { // uses Dispatchers.Main context
val response = withContext(Dispatchers.IO) { // change context to background thread
// blocking I/O operation
post(SERVER_URL, files = listOf(File(path).fileLike(name = "Image.jpg")))
}
findViewById<TextView>(R.id.image_desc).text = "Image contains: ${response?.text}"
}