Search code examples
javaandroidlambdakotlinfunctional-interface

Getting an interface reference inside a lambda function


Consider the following code:

val hwnd = Handler()
hwnd.postDelayed(object : Runnable {
        override fun run()
            hwnd.postDelayed(this, 5000)
        }
}, 5000)

This way, I can post the same Runnable to the Handler by using this (which refers to the Runnable) in the run() method. But how could I do the same using only a lambda expression?

val hwnd = Handler()
hwnd.postDelayed({
    //How to get "this" here?
}, 5000)

Is that even possible?


Solution

  • Since default lambda conversion gives you lambda with signature of () -> Unit, that means underlying Runnable is completely hidden.

    You have to either deal with manual object creation, or write a wrapper extension function that will consume lambda with another signature:

    // custom extension function for handler
    inline fun Handler.postDelayed(delayMilis: Long, crossinline runnable: (Runnable) -> Unit) = postDelayed(object : Runnable{
        override fun run() {
            runnable(this)
        }
    }, delayMilis)
    

    Then at calling side you will be provided with Runnable object as lambda parameter (only parameter: it):

    hwnd.postDelayed(5000){ 
        // it : Runnable
        hwnd.postDelayed(it, 5000)
    }
    

    Or if you want to get really fancy, change extension parameter to Handler.(Runnable) -> Unit, then you will be able to call:

    hwnd.postDelayed(5000){ 
        // this : Handler, it : Runnable
        postDelayed(it, 5000)
    }