【问题标题】:Coroutine calling API Android协程调用API Android
【发布时间】:2018-06-13 15:02:16
【问题描述】:

我必须异步调用 API。为此,我正在使用协程,但我必须等到调用 API 才能加载数据。问题是下一个:

等待没有按我的意愿工作,它没有等到 API 提供所有数据。

等待是我需要的吗?代码如下:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_see)
    launch { loaddata() }
    /* some other code here*/
}

suspend fun loadData(){
    val readData = async { read() }
    readData.join()
    readData.await()
    val showScreen = async { refreshList() }
    showScreen.join()
    showScreen.await()
}


fun read(){
    val stringRequest = object : StringRequest(Request.Method.POST, URL, Response.Listener<String>{ s ->
        try {
                val array = JSONArray(s)
                for (i in 0..array.length() - 1) {
                    val objectAccount = array.getJSONObject(i)
                    val account = Account(
                            objectAccount.getString(value),
                            objectAccount.getString(value),
                            objectAccount.getString(value))
                    listAccount.add(account)
                }
        }catch (e: JSONException){
            e.printStackTrace()
        }
    }, Response.ErrorListener { error: VolleyError? -> Log.e("error", "error")  }){
        override fun getParams(): Map<String, String> {
            val params = HashMap<String, String>()
            params.put("password", value)
            params.put("idaccount", value)
            return params
        }
    }
    val  requesQueue = Volley.newRequestQueue(this)
    requesQueue.add<String>(stringRequest)
}

【问题讨论】:

    标签: android asynchronous async-await kotlin coroutine


    【解决方案1】:

    通常你不应该打电话给async function

    requesQueue.add<String>(stringRequest)
    

    async协程构建器中

    async {}
    

    解决方案#1

    您可以将read() 方法更改为同步请求。 Can I do a synchronous request with volley? 并使用CommonPool 运行它

    async(CommonPool) {
        read()
    }
    

    解决方案 #2

    将您的异步 http 调用包装到 suspend function

    我不熟悉 Volley,所以可能代码需要调整

    suspend fun read() {
        return suspendCancellableCoroutine { continuation ->
    
            val stringRequest = object : StringRequest(Request.Method.POST, URL, Response.Listener<String> { s ->
                try {
                    val array = JSONArray(s)
                    for (i in 0..array.length() - 1) {
                        val objectAccount = array.getJSONObject(i)
                        val account = Account(
                                objectAccount.getString(value),
                                objectAccount.getString(value),
                                objectAccount.getString(value))
                        listAccount.add(account)
                    }
                } catch (e: JSONException) {
                    e.printStackTrace()
    
                    // notice this
                    continuation.resumeWithException(e)
                }
                // notice this
                continuation.resume()
    
            }, Response.ErrorListener { error: VolleyError? ->
                Log.e("error", "error")
    
                // notice this
                if (!continuation.isCancelled)
                    continuation.resumeWithException()
    
            }) {
                override fun getParams(): Map<String, String> {
                    val params = HashMap<String, String>()
                    params.put("password", value)
                    params.put("idaccount", value)
                    return params
                }
            }
    
            val requesQueue = Volley.newRequestQueue(this)
            requesQueue.add<String>(stringRequest)
    
            continuation.invokeOnCompletion {
                if (continuation.isCancelled)
                    try {
                        cancel()
                    } catch (ex: Throwable) {
                        //Ignore cancel exception
                    }
            }
        }
    }
    

    然后这样称呼它

    suspend fun loadData(){
    
        read()
    
        val showScreen = async { refreshList() }
        showScreen.join()
        showScreen.await()
    }
    

    【讨论】:

    • 完美!解决方案 1 有效!!你能解释一下什么是 CommonPool 吗?我也做了一些可行的解决方案,但我不知道它是否正确,我在添加 requestQueue 后添加了此代码:requesQueue.addRequestFinishedListener { cl.refresh() }
    • 它就像一个线程池,在后台线程池上运行 read() 方法,这样它就不会阻塞你的主线程
    猜你喜欢
    • 2023-01-05
    • 2020-01-30
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    • 2020-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多