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

时间:2018-10-06 22:55:30

标签: android rx-java retrofit2 rx-java2

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

api定义如下:

[WinError 2] The system cannot find the file specified
[cmd: ['C:\\ProgramData\\Anaconda3\\python.exe', '']]
[dir: C:\Program Files\Sublime Text 3]
[path: C:\Program Files\Microsoft MPI\Bin\;C:\Users\Joshu\AppData\Local\Programs\Python\Python36\Scripts\;C:\Users\Joshu\AppData\Local\Programs\Python\Python36\;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files\Java\jdk1.8.0_131\bin;C:\Program Files (x86)\Calibre2\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\dotnet\;C:\Program Files (x86)\GtkSharp\2.12\bin;C:\Program Files\MATLAB\R2017b\runtime\win64;C:\Program Files\MATLAB\R2017b\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Program Files\nodejs\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files\Git\cmd;C:\Users\Joshu\AppData\Local\Microsoft\WindowsApps;C:\Users\Joshu\AppData\Roaming\npm;C:\Users\Joshu\AppData\Roaming\Dashlane\5.3.2.14186\bin\Firefox_Extension\{442718d9-475e-452a-b3e1-fb1ee16b8e9f}\components;C:\Users\Joshu\AppData\Roaming\Dashlane\5.3.2.14186\ucrt;C:\MinGW\bin;C:\Program Files (x86)\Microsoft Visual Studio\Shared\Anaconda3_64;]
[Finished]

然后管理所有内容的服务:

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

然后在我的活动中,每当EditText内容更改时,我都会进行此调用:

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

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

1 个答案:

答案 0 :(得分:8)

首先,您想得对,为每个变更事件创建一个$(document).ready (function () { // Init of script1.js // Init of script2.js }) 效率很低。

有两种解决方法:

一个

您可以使用RxBinding进行文本更改Observable,现在您可以Observable将文本更改更改为apiService调用,甚至可以一次性使用。

flatMap

两个

您可以使用disposable = RxTextView.textChanges(editText) .switchMap { ApiService().checkUsername(it) } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe { updateUi(it) } 用作Subject更改的通道,如下所示:

EditText

现在还可以一次性使用!

注意:如果人们使用的是将View逻辑与中间人逻辑分开的特定体系结构模式,则有时会倾向于使用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) } 技术,如果不受此约束,{{1} }是必经之路。

还有值得一提的是,这两种方法将为您提供订阅每个文本更改事件时所不具备的功能,例如使用诸如SubjectRxBinding这样的流控制运算符。

编辑

使用debounce代替onBackpressureLatest,请参见Here