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

Inn*_*ve1 1 android rx-java retrofit2 rx-java2

我有一个活动,每次用户输入更改时我都会向其发出网络请求.

api定义如下:

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

然后是管理它的服务:

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)
  }
}
Run Code Online (Sandbox Code Playgroud)

然后在我的活动中,每当EditText内容发生变化时,我都会进行此调用:

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

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

Ahm*_*mal 8

首先,你正在思考,Observable为每个变革事件创建一个远非有效.

有两种方法:

您可以使用RxBinding来更改文本Observable,现在您可以flatMap将文本更改为apiService调用,最多可以更改为一次性.

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

您可以使用a Subject作为EditText此类更改的通道:

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) }
Run Code Online (Sandbox Code Playgroud)

现在这也是一次性的!

注意:人们有时倾向于使用这种Subject技术,如果他们使用的是将View逻辑与中间人逻辑分开的特定体系结构模式,如果你不受限制,那RxBinding就是要走的路.

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

编辑:

用来switchMap代替flatMap,看看这里的差异