I'm implement an TextInputEditText with RxBinding.
Problem: When I do some math operation on first TextInputEditText and set the result to another TextInputEditText, The screen is not responding. When I start to type another digit, its not displayed in the edit text. I know why this happened, but don't know how to fix. For more detail, please check the code below.
Code:
class NumberSystemFragment : Fragment() {
override fun onCreateView() { ... }
override fun onViewCreated() {
binding?.run {
// It still ok if just observe a single edit text
etBinary.observeInput().subscribe {
val dec = it.fold(0L) { acc, el ->
(acc * 2) + el.digitToInt(radix = 2)
}
val oct = dec.toString(8)
val hex = dec.toString(16)
etDecimal.setText(dec.toString())
etOctal.setText(oct)
etHexadecimal.setText(hex)
}
// But, when I add more EditText, the screen will not responding.
// I know why this can happen, because when I set the result from operation above,
// and display it to another EditTexts, then the other EditText will begin to observe its input too.
// Then the racing condition or whatever it is, will occur.
etDecimal.observeInput().subscribe {
val bin = it.toLong().toString(2)
val oct = it.toLong().toString(8)
val hex = it.toLong().toString(16)
etBinary.setText(bin)
etOctal.setText(oct)
etHexadecimal.setText(hex)
}
}
}
private fun <T : EditText> T.observeInput() =
RxTextView.textChanges(this)
.skipInitialValue()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(CharSequence::toString)
.publish()
.refCount()
}
Sorry, I'm new with RxJava, RxBinding, etc.
Two issues.
First of all, make these extension method changes:
private fun <T: EditText> T.observeInput() =
RxTextView.textChanges(this)
.skipInitialValue()
.map(CharSequence::toString) // <------------------ order matters
.distinctUntilChanged() // <----------------------- order matters
.observeOn(AndroidSchedulers.mainThread())
.publish()
.refCount()
private fun TextInputEditText.setText(text: CharSequence, onlyIfChanged: Boolean) {
if (onlyIfChanged) {
if (Objects.equals(this.text.toString(), text.toString())) {
return;
}
}
this.setText(text);
}
Then, update your onNext handlers:
// etBinary
// store calculation data
try {
Log.d("XYZ-etBinary", t);
val decResult = t.fold(0L) { acc, element ->
(acc * 2) + element.digitToInt(2)
}
val octResult = decResult.toString(8)
val hexResult = decResult.toString(16).uppercase()
// and display the results to another edit text which corresponds with their radix representation
etDecimal.setText(decResult.toString(), true)
etOctal.setText(octResult, true)
etHexadecimal.setText(hexResult, true)
} catch (e: Throwable) {
Log.e("XYZ-etBinary", e.message.toString())
}
// etDecimal
// store calculation data
try {
Log.d("XYZ-etDecimal", t);
val binResult = t.toLong().toString(2)
val octResult = t.toLong().toString(8)
val hexResult = t.toLong().toString(16).uppercase()
// and display the results to another edit text which corresponds with their radix representation
etBinary.setText(binResult, true)
etOctal.setText(octResult, true)
etHexadecimal.setText(hexResult, true)
} catch (e: Throwable) {
Log.e("XYZ-etDecimal", e.message.toString())
}
Also posted it as a Pull Request on your repo: https://github.com/dansampl/EditTextWithRxJavaSampleApp/pull/1/files