Vlad Skurtolov
Vlad Skurtolov

Reputation: 1054

Explain this Kotlin function structure

I am working with this Kotlin function. I know that we have a function called mPasswordView!!.setOnEditorActionListener, that take parameter TextView.OnEditorActionListener, but what's that after it? we have curly brackets inside parameter?

mPasswordView!!.setOnEditorActionListener(TextView.OnEditorActionListener { textView, id, keyEvent ->
    if (id == R.id.login || id == EditorInfo.IME_NULL) {
        attemptLogin()
        return@OnEditorActionListener true
    }
    false
})

Upvotes: 2

Views: 1869

Answers (1)

zsmb13
zsmb13

Reputation: 89548

The feature used in your example is a SAM constructor. The setOnEditorActionListener listener takes an OnEditorActionListener as its parameter. This interface only has a single method that you have to implement, which makes it a Single Abstract Method (SAM) interface.

The full syntax for using this method in Java would be:

mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        attemptLogin();
        return true;
    }
});

The one-to-one conversion to Kotlin would give you:

mPasswordView.setOnEditorActionListener(object: TextView.OnEditorActionListener{
    override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean {
        attemptLogin()
        return true
    }
})

Kotlin, however, allows you to use methods that take SAM interfaces as their parameter with a more concise syntax, by passing in a lambda instead. This is called a SAM conversion:

mPasswordView.setOnEditorActionListener { v, actionId, event ->
    attemptLogin()
    true
}

SAM conversions automatically determine which interface this lambda corresponds to, but you can specify it explicitly by using something called a SAM constructor, this is what's in your sample code. A SAM constructor returns an object that implements the given interface, and makes the lambda you've passed to it its single method's implementation.

mPasswordView.setOnEditorActionListener( TextView.OnEditorActionListener { v, actionId, event ->
    attemptLogin()
    true
})

This is redundant in this specific situation, because there is only one method called setOnEditorActionListener. But if there were multiple methods with this same name, that took different interfaces as parameters, you could use the SAM constructor to specify which overload of the method you want to call.

Official docs about SAM conversions

Upvotes: 9

Related Questions