みんな大好きRxBinding1 ですが、ちょっとハマることがあったのでメモ。
RxTextView#textChanges()
で EditText
の入力イベントを監視する。その時に重複した入力をdistinctUntilChanged()
で削ろうとしたら以降何もeventが流れない現象に遭遇した。
RxTextView.textChanges(editText) .distinctUntilChanged() // ここでevnetが止められるから .observeOn(AndroidSchedulers.mainThread()) .subscribe { Log.d("SampleApp", it.toString()) // ここは実行されない }
textChanges()
は内部ではTextWatcher
を使っていて、これがTextの変更を検出するとCharSequence
を返してくれるのだが、こいつはmutableで毎度同じinstanceを返すのだ。同じinstanceなのでchangeしたと見なされずいつまでたっても次のeventが流れてこない。
なので、CharSequence
からStringを取り出してやれば想定していた挙動になる。
RxTextView.textChanges(editText) .map { it.toString() } // ここでStringに変換すると .distinctUntilChanged() .observeOn(AndroidSchedulers.mainThread()) .subscribe { Log.d("SampleApp", it.toString()) // ここが実行される }
そもそもなんで RxTextView#textChanges()
で入力の重複を防ぎたかったかというと、機種依存でSoftware Keyboardのsearch button
をtapした時にtextChanges
のeventがemitされちゃう場合があって、これを防ぎたかったから。これはRxTextView
というよりは、内部で使われているTextWatcher
でeventが発火しているからなんだけど、keyboardの機種依存周りつらすぎてなんか仕様とか作って統一して欲しい…