首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有截击的异步协程

带有截击的异步协程
EN

Stack Overflow用户
提问于 2021-07-15 00:07:31
回答 1查看 50关注 0票数 1

我正在尝试将我的宠物应用程序转换为使用协程而不是回调。我已经完成了一半,但是我看不到如何绕过这个函数中的回调。有没有一种方法可以使用异步来摆脱回调,或者我爬错了树?

这就是我到目前为止所知道的:

代码语言:javascript
复制
const val url = "https://pokeapi.co/api/v2/pokemon/"

class PokeClient {
    fun getPokemonData(context: Context, successCallBack: (Pokemon) -> Unit, pokemonName: String) = runBlocking {
    val queue = Volley.newRequestQueue(context)
    val request = url.plus(pokemonName)

    var deferredResult = async {
        val stringRequest = StringRequest(Request.Method.GET, request, Response.Listener<String> { response ->
            val jObj = JSONObject(response)
            val imgUrl = jObj
                .getJSONObject("sprites")
                .getJSONObject("other")
                .getJSONObject("official-artwork")
                .getString("front_default")

            val inputStream = URL(imgUrl).openStream()
            successCallBack(Pokemon(name = jObj.getString("name"), image = BitmapFactory.decodeStream(inputStream)))
        }, Response.ErrorListener {
            val toast = Toast.makeText(context, "error talking to professor Oak!", Toast.LENGTH_SHORT)
            toast.show()
        })

        queue.add(stringRequest)
        }

        deferredResult.await()
    }
}

有什么想法吗?

谢谢你,Android新手

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-07-15 00:31:35

本质上,你需要将带有回调代码块的网络调用转换成可以从任何协程调用的挂起函数,这可以使用suspendCoroutine函数来完成,它基本上为你提供了一个coroutine对象,在你的例子中,它可以用来从响应回调中返回数据

代码语言:javascript
复制
suspend fun getPokemon() = suspendCoroutine<Pokemon> { cont ->
    val queue = Volley.newRequestQueue(this)
    val url = "https://pokeapi.co/api/v2/pokemon/"

    val stringRequest = StringRequest(Request.Method.GET, url,
        Response.Listener<Pokemon> { response ->   
            val jObj = JSONObject(response)
            val imgUrl = jObj.getJSONObject("sprites")
                .getJSONObject("other")
                .getJSONObject("official-artwork")
                .getString("front_default")

            val inputStream = URL(imgUrl).openStream()
            /* call continuation.resume and pass your object */
            cont.resume(Pokemon(name = jObj.getString("name"), image = BitmapFactory.decodeStream(inputStream)))      
        },
        Response.ErrorListener { 
            /* if network call fails then post appropriate error */
            cont.resumeWithException(YourExceptoin) 
        })
    queue.add(stringRequest)
}

现在,您可以从协程调用此function并获得一个Pokemon,如下所示

代码语言:javascript
复制
runBlocking{
  try { val pokeMon = getPokemon() }
  catch(e: Exception) { Log.d(TAG, "Cant get pokemon") }
}

注意:只使用runBlocking进行学习和探索是可以的,否则这不是一个好主意,请使用launchasync

编辑:如注释中所述,如果您需要支持取消,也可以使用suspendCancellableCoroutine (对于结构化并发,您应该这样做)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68381541

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档