Lars Blumberg
Lars Blumberg

Reputation: 21381

How to reference "this" within anonymous listeners when using short notation?

In Kotlin, is there a way to reference the listener instance when using this short notation for anonymous classes? In this case this refers to outer context (e.g. the Activity instance) where view is defined:

view.setOnClickListener {
    val self: View.OnClickListener = this // Not compiling, "this" references outer context
}

When using the longer notation where you explicitly state the interface to be implemented and where you explicitly override the callback method, the listener can be referenced through this:

view.setOnClickListener(object: View.OnClickListener {
    override fun onClick(v: View) {
        val self: View.OnClickListener = this // Ok
    }
})

Upvotes: 23

Views: 4654

Answers (4)

William Reed
William Reed

Reputation: 1844

Somewhat related - here is an example of removing a listener from the listener itself that came about after not being able to refer to itself as reported by the accepted answer

    @Suppress("JoinDeclarationAndAssignment")
    fun View.foo() {
        // can't combine this with the assignment since it is referenced within the
        // body of the layout listener to remove itself
        lateinit var layoutListener: ViewTreeObserver.OnGlobalLayoutListener

        layoutListener = ViewTreeObserver.OnGlobalLayoutListener {
            // ... do something ...
            viewTreeObserver.removeOnGlobalLayoutListener(layoutListener)
        }

        viewTreeObserver.addOnGlobalLayoutListener(layoutListener)
    }

I don't typically see lateinit used in a local method field so this wasn't immediately obvious to me

Upvotes: 1

jamian
jamian

Reputation: 1662

You can get that resolved by adding an @ActivityName in front of 'this' reference For example if your Activity name was MainActivity the solution would be:

view.setOnClickListener {
    val self: View.OnClickListener = this@MainActivity 
}

Upvotes: 10

Steeven Sylveus
Steeven Sylveus

Reputation: 49

 val animation = object : Animation() {
        override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
            val layoutParam: RelativeLayout.LayoutParams? = playerView.layoutParams as RelativeLayout.LayoutParams?
            layoutParam?.topMargin = convertDpToPixel(position, this@SurahActivity).toInt()
            playerView.layoutParams = layoutParam
        }
    }

Upvotes: 2

Kirill Rakhman
Kirill Rakhman

Reputation: 43831

The term short notation for anonymous classes is not entirely correct. It's actually a short notation for anonymous functions, i.e. lambdas. Of course under the hood they are compiled to classes but from a programming language point of view, anonymous functions don't have identities and therefore it doesn't make sense to refer to their instances via this.

Upvotes: 11

Related Questions