【问题标题】:RxJava2 how to update existing subscription when request parameter changesRxJava2如何在请求参数更改时更新现有订阅
【发布时间】:2019-03-12 01:09:21
【问题描述】:

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

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)
  }
}

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

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

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

【问题讨论】:

    标签: android rx-java retrofit2 rx-java2


    【解决方案1】:

    首先,您的想法是正确的,为每个更改事件创建一个Observable 远没有效率。

    有两种方法:

    一个

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

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

    两个

    您可以使用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) }
    

    现在也只剩下一次性了!

    注意:如果人们使用将视图逻辑与中间人逻辑分开的特定架构模式,人们有时倾向于使用Subject 技术,如果您不受此约束,RxBinding 就是这种方式去。

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

    编辑

    switchMap代替flatMap,看Here的区别

    【讨论】:

    • 您可能想建议使用switchMap() 运算符而不是flatMap()switchMap() 将在启动下一个 observable 时取消订阅前一个 observable。
    猜你喜欢
    • 1970-01-01
    • 2020-06-03
    • 1970-01-01
    • 1970-01-01
    • 2017-05-04
    • 2019-06-05
    • 2021-03-18
    • 2021-09-08
    • 2021-01-28
    相关资源
    最近更新 更多