android - RxJava2 如何在请求参数更改时更新现有订阅

标签 android rx-java retrofit2 rx-java2

我有一项 Activity ,每当用户输入发生变化时,我都会在该 Activity 上发出网络请求。

api定义如下:

interface Api {
  @GET("/accounts/check")
  fun checkUsername(@Query("username") username: String): Observable<UsernameResponse>
}

然后是管理这一切的服务:

class ApiService {

  var api: Api

  init {
    api = retrofit.create(Api::class.java)
  }

  companion object {
    val baseUrl: String = "https://someapihost"
    var rxAdapter: RxJava2CallAdapterFactory = RxJava2CallAdapterFactory.create()
    val retrofit: Retrofit = Retrofit.Builder()
            .baseUrl(baseUrl)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(rxAdapter)
            .build()


}

  fun checkUsername(username: String): Observable<UsernameResponse> {
    return api.checkUsername(username)
  }
}

然后在我的 Activity 中,每当 EditText 内容发生变化时,我都会调用:

  private fun checkUsername(username: String) {
      cancelSubscription()
      checkUsernameDisposable = ApiService()
            .checkUsername(username)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
              updateUi(it)
      }
  }

因此,每次输入更改时,都会创建一个新的一次性对象。这显然是不正确的。我想要做的是用新网络调用的结果更新现有订阅。

最佳答案

首先,您的想法是对的,为每个更改事件创建一个 Observable 效率很低。

有两种方法:

一个

您可以使用 RxBinding获取文本更改 Observable,现在您可以 flatMap 将文本更改发送到您的 apiService 调用,减少到一次性。

disposable = RxTextView.textChanges(editText)
    .switchMap { ApiService().checkUsername(it) }
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe { updateUi(it) }

两个

您可以使用 Subject 作为更改 EditText 的 channel ,如下所示:

val editTextChangesSubject: PublishSubject<String> = PublishSubject.create()

// when the editText changes call
editTextChangesSubject.onNext(newText)

disposable = editTextChangesSubject
        .switchMap { ApiService().checkUsername(it) }
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe { updateUi(it) }

现在也只剩下一次性用品了!

注意:如果人们使用将 View 逻辑与中间人逻辑分开的特定架构模式,人们有时倾向于使用 Subject 技术,如果您不受此约束,RxBinding 是要走的路。

此外,如果值得一提,这两种方法将为您提供订阅每个文本更改事件时不存在的权力,例如使用流控制运算符,如 debounceonBackpressureLatest.

编辑:

使用switchMap代替flatMap,区别见Here

关于android - RxJava2 如何在请求参数更改时更新现有订阅,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52684030/

相关文章:

android - 如何在 Android 中压缩两个 Observables?

Android 优点和缺点 : Event Bus and RxJava

java - 是否有更干净的方法使用 RxJava 来适应标准观察者/监听器服务?

android - 安装从单一来源创建的 APK

android - 为什么我在创建/更新通知时会收到 RemoteServiceException?

android - 使用json获取当前位置

java - 依次使用不同的请求正文发出多个 API 请求

java - 使用 opencv (Java) 的阈值图像

java - Retrofit2 - 无法使用 PartMap 上传文件

android - Retrofit 2 - 如何在接收 JSON 响应时显示进度条