Observable.combineLatest type inference in kotlin
Asked Answered
M

2

26

I'm using RxJava2, Kotlin-1.1 along with RxBindings in my project.

I have simple login screen with 'login' button disabled by default, I want to enable the button only when username and password edittext fields are not empty.

LoginActivity.java

Observable<Boolean> isFormEnabled =
    Observable.combineLatest(mUserNameObservable, mPasswordObservable,
        (userName, password) -> userName.length() > 0 && password.length() > 0)
        .distinctUntilChanged();

I'm unable to translate the above code from Java to Kotlin:

LoginActivity.kt

class LoginActivity : AppCompatActivity() {

  val disposable = CompositeDisposable()

  private var userNameObservable: Observable<CharSequence>? = null
  private var passwordObservable: Observable<CharSequence>? = null

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_login)
    initialize()
  }

  fun initialize() {
    userNameObservable = RxTextView.textChanges(username).skip(1)
        .debounce(500, TimeUnit.MILLISECONDS)
    passwordObservable = RxTextView.textChanges(password).skip(1)
        .debounce(500, TimeUnit.MILLISECONDS) 
  }

  private fun setSignInButtonEnableListener() {
    val isSignInEnabled: Observable<Boolean> = Observable.combineLatest(userNameObservable,
        passwordObservable,
        { u: CharSequence, p: CharSequence -> u.isNotEmpty() && p.isNotEmpty() })
  }
}

I assumed it's something related to type inference of the third argument in combinelatest, but I don't get the issue properly by reading the error message: Type Inference issue

Microstructure answered 10/3, 2017 at 18:52 Comment(0)
B
43

Your issue is that the compiler can't figure out which override of combineLatest to call, because multiple ones have functional interfaces as their third parameter. You can make the conversion explicit with a SAM constructor like this:

val isSignInEnabled: Observable<Boolean> = Observable.combineLatest(
        userNameObservable,
        passwordObservable,
        BiFunction { u, p -> u.isNotEmpty() && p.isNotEmpty() })

Ps. Thanks for asking this question, it helped me figure out that I was initially wrong about this one that turns out to be the same problem, which I've now updated with this solution as well. https://mcmap.net/q/488796/-kotlin-and-rxjava-why-is-my-single-zip-not-compiling

Bide answered 10/3, 2017 at 19:22 Comment(2)
Took me so long figure this out.Ejaculate
This link may be helpful in connection with this answer.Cosmogony
L
40

You can use RxKotlin which gives you helper methods for SAM ambiguity issue.

val isSignInEnabled: Observable<Boolean> = Observables.combineLatest(
    userNameObservable,
    passwordObservable)
    { u, p -> u.isNotEmpty() && p.isNotEmpty() })

As you can see, in RxKotlin use Observables instead of Observable

Lineberry answered 5/11, 2017 at 2:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.