【问题标题】:Can/should I write these interdependent Volley calls sequentially in Kotlin?我可以/应该在 Kotlin 中按顺序编写这些相互依赖的 Volley 调用吗?
【发布时间】:2020-11-07 14:32:47
【问题描述】:

我是第一次在 Android Studio 中使用 Kotlin 编写一个 Android 应用程序。我对异步编程很陌生。

应用程序将向用户显示一些数据,这些数据将使用 Volley 从 REST API 获取。为了让一组有意义的数据一起显示,需要来自三个 GET 请求的响应。

第一个 GET 请求不需要其他两个 GET 请求的输出来设置其查询参数。

第二个和第三个 GET 请求都需要第一个 GET 请求的输出来设置它们的查询参数,但它们不依赖于彼此的输出,所以这两个请求中的哪一个被调用或先返回。

一旦所有三个请求都返回了响应,结果就会被组合成一些有意义的信息,然后显示给用户。

我实现的方式是从我的顶级例程调用第一个 GET 请求,然后从第一个请求的响应侦听器函数中依次调用第二个和第三个请求。从第二个和第三个请求的响应侦听器函数调用最后一个函数,该函数组装信息并将其显示给用户;这个最终函数首先将计数器加一,然后仅在计数器达到值 2 时才执行其余的工作,这意味着只有在后者调用该函数时才会执行该工作两个请求返回。

如果我能以这样一种方式编写代码,即所有三个 Volley GET 请求都可以从我的顶层依次调用,我觉得它会“更好”(在某种程度上我不太知道如何描述)例程,然后是在我的顶级例程中调用这些 GET 请求后,依次组装并向用户显示数据。

这似乎要求对第二个和第三个 GET 请求的调用在第一个请求返回之前不要“触发”,并且汇编和显示代码在所有三个请求都返回之前不要“触发”。但我不知道如何在 Kotlin 中表达这一点。

我是否有一种很好、简洁、标准的方式来顺序编写这段代码,还是我应该停止认为仅仅为了它而顺序编写这段代码会更好?

【问题讨论】:

  • 最惯用的方式是使用协程。内部协程调用第一个 API,然后与另外两个调用异步{}。等待两者的结果,然后显示。 Volley 已经很老了,不确定它是否支持协程。 Retrofit 是 Android 上 REST Api 的事实标准库(并支持协程)。
  • 改造哈...想知道我是怎么错过的。稍后我会尝试一下,让你知道我的进展情况!

标签: android kotlin asynchronous android-volley


【解决方案1】:

就像我在评论中提到的,最惯用的 Kotlin 方式是使用协程。
这是一个例子:

您将 API 调用标记为 suspend 函数:

interface ApiService {
    @GET("foo")
    suspend fun getFoo(): Foo

    @GET("bar1")
    suspend fun getBar1(): Bar1

    @GET("bar2")
    suspend fun getBar2(): Bar2
}

我们创建该接口的一个实例(有关详细信息,请参阅Retrofit documentation):

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.my-website.com/")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

GitHubService service = retrofit.create(GitHubService.class);

然后,我们首先调用foo,然后调用bar1bar2。我们终于等到两个都这样结束了。

GlobalScope.launch{
   val fooResult = service.getFoo()

   // you can use fooResult if you need for arguments of the other two.
   // you fire both events, and get a Deferrable to it.
   val deferrableBar1 = async { service.getBar1() }
   val deferrableBar2 = async { service.getBar2() }


   // call await() for both. This makes sure that you get results of both before you continue.
   val bar1Result = deferrableBar1.await()
   val bar2Result = deferrableBar2.await()

   // use the results from API
   showInUI(fooResult,bar1Result,bar2Result)

}

请注意,您必须将 try-catch 添加到处理错误的调用中。

【讨论】:

  • 抱歉,在收到您最初的评论后,我再也没有回来查看过。谢谢你的例子,我最终通过反复试验学到了很多关于协程的知识,我很喜欢它们! ;)
猜你喜欢
  • 1970-01-01
  • 2020-07-22
  • 2014-10-11
  • 2016-04-07
  • 1970-01-01
  • 2014-12-04
  • 1970-01-01
  • 2015-07-08
  • 1970-01-01
相关资源
最近更新 更多