9

I'm converting a project in Java to Kotlin and I'm surprise that interface made the code heavier in Kotlin than in Java.

Example: I want to set the onBackPressListener in MainActivity from MyFragment.

File 1: MainActivity, File 2: MyFragment, File 3: OnBackPressedListener (Interface)

File 1 in Java, File 2 in Kotlin, File 3 in Java:

activity.setOnBackPressed { /* Do something */ }

File 1 in Kotlin, File 2 in Kotlin, File 3 in Java:

activity.setOnBackPressed(OnBackPressedListener { /* Do something */ })

File 1 in Kotlin, File 2 in Kotlin, File 3 in Kotlin:

activity.setOnBackPressed(object: OnBackPressedListener {
            override fun onBackPressed() {
                /* Do something */
            }
        })

Is it possible to have the 3 files in Kotlin and use lambda to set the listener ? (This is so frustrating to get more code in Kotlin..)

Thanks

0

2 Answers 2

10

The lambda version works only when kotlin interop with java because SAM Conversions, see the official documents.

Also note that this feature works only for Java interop; since Kotlin has proper function types, automatic conversion of functions into implementations of Kotlin interfaces is unnecessary and therefore unsupported.

So if you want use lambda to set the listener with pure kotlin, you can define your listener and setOnBackPressed method like this:

var listener: (() -> Unit)? = null

fun setOnBackPressed(l: () -> Unit) {
    listener = l
}

then invoke it by:

listener?.invoke()
Sign up to request clarification or add additional context in comments.

3 Comments

What does invoke actually do?
@IgorGanapolsky since lambdas in kotlin are compiled into Function class objects with only invoke() method inside - invoke() just execute lambda block. Usually we just write lambda() which is same as lambda.invoke(). But with nullable lambdas we have to use question mark for null safety
Would inline and crossinline play any role on this particular execution?
6

You use Java style while use Kotlin =)

If you really want to use OnBackPressedListener you can just wrap it in inline function, like:

inline fun backPress(crossinline action:()->Unit):OnBackPressedListener {
    return object: OnBackPressedListener {
        override fun onBackPressed() {
            action()
        }
    }
}

And then just set listener

activity.setOnBackPressed(backPress {  
/* Do something */
})

3 Comments

What does crossinline action do? And why do we have to create a whole new object...
@IgorGanapolsky we create a new object only because author of question wanted to use it. Crossinline just restricts to use "return" in inlined lambda because it can finish wrong function
So your crossinline returns nothing?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.