我有一个活动,每次用户输入更改时都会向我发出网络请求。
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)
}
}
因此,每次输入更改时,这都会创建一个新的一次性用品。这显然是不正确的。我想做的是使用新网络通话的结果更新现有订阅。
答案 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} }是必经之路。
还有值得一提的是,这两种方法将为您提供订阅每个文本更改事件时所不具备的功能,例如使用诸如Subject
或RxBinding
这样的流控制运算符。
编辑:
使用debounce
代替onBackpressureLatest
,请参见Here