Setting anonymous interface in Kotlin [duplicate]

徘徊边缘 提交于 2019-12-12 13:41:31

问题


I have an interface in my Adapter class:

interface OnItemClickListener {
    fun onItemClick(view: View)
}

TAKE NOTE that my interface is in Kotlin.

which I want to set via this method:

public fun setItemClickListener(itemClickListener: OnItemClickListener) {
    this.onItemClickListener = itemClickListener
}

How do I use the setItemClickListener method in my Fragment class like what I used to do in Java? i.e.

adapter.setItemClickListener(new OnItemClickListener() {
   @Override
   public void onItemClick(View view) {
    // do something
   }
}

I know that I can use an onItemTouchListener but I am still new to Kotlin and I'm trying to learn some techniques like Lambdas and such.


回答1:


The problem is that your interface is defined in Kotlin (since it has fun). Lambdas can only be used for Java interfaces:

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 in Kotlin you are supposed to use

public fun setItemClickListener(itemClickListener: (View) -> Unit)

instead of defining OnItemClickListener. You could also create a factory method:

// in Adapter's companion object
public inline fun OnItemClickListener(body: (View) -> Unit) = object : OnItemClickListener {
    override fun onItemClick(view: View) { body(view) }
}

and then

adapter.setItemClickListener(Adapter.OnItemClickListener { view -> ... })



回答2:


Without lambda you can do it like this

adapter.setItemClickListener(object :View.OnItemClickListener{
            override fun onItemClick(p0: View?) {

            }
        })



回答3:


This is how we do it in lambda

adapter.setItemClickListener{ Log.i("Adapter", "onItemClick event fired on " + it.id) }

Here it is the instance of View which is the parameter of onItemClick method.

More information on it is here https://kotlinlang.org/docs/reference/lambdas.html#it-implicit-name-of-a-single-parameter

You can find more information in Kotlin docs here https://kotlinlang.org/docs/reference/lambdas.html#lambda-expressions-and-anonymous-functions




回答4:


If you want to assign interface with single method, you can just write this:

adapter.setItemClickListener { view ->
    /* some code here */
}

Or even better:

adapter.setItemClickListener { 
    /* some code here, to use "view" use keyword "it" */
}

If you want look deeper, let's analize signature of your method:

public fun setItemClickListener(itemClickListener: OnItemClickListener)

this is actually equals to

public fun setItemClickListener(singleMethodListener: (View) -> Unit)

If your last argument is function, you can just forget about '()', and pass lambda. One more example:

public fun setItemClickListener(parameter: Int, singleMethodListener: (View) -> Unit)

to call method above, your code should be:

item.setItemClickListener(0) { /* lambda here */ }

The problem is when you have interface with more than one method, because then you cannot pass lambda :(

Example:

interface OnItemClickListener {
     fun onItemClick(view: View)
     fun onDoubleItemClick(view: View)
}

Then, you cannot pass sample labda, because you have to define 2 methods. Then, you have to do the same thing like in java, but in other syntax:

adapter.setItemClickListener(object : OnItemClickListener {
    /* method declarations here, like in java */
})

I hope I have explained base-lambda syntax in Kotlin :D Any question? Ask ;)



来源:https://stackoverflow.com/questions/50921677/setting-anonymous-interface-in-kotlin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!