Kotlin中OnclickListener方法的区别

时间:2017-09-19 05:32:59

标签: android kotlin

我正在学习Kotlin。在此之前,我曾使用Java进行Android开发。 Kotlin是一门很好的学习语言。我在使用setOnClickListener(View.OnClickListener)时感到困惑。我在Android Studio上看到了两个提示。

image

我知道如何工作或定义它们。

实施OnClickListerner

的第一种方式
 send_button.setOnClickListener(object : View.OnClickListener{
       override fun onClick(p0: View?) {
           TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
       }
   })

这是实施OnClickListener

的第二种方式
 send_button.setOnClickListener {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

据我所知,第二种方法基于lambda。但我无法正确理解这些方法。

所以,我的问题是:这些方法有什么区别?如果它们不同,哪一个更好,为什么?

2 个答案:

答案 0 :(得分:5)

它们指的是相同的功能,但是以不同的方式编写。第一种是调用接受setOnClickListener()对象的OnClickListener函数的典型方法。

第二个使用lambda表达式。它有效,因为View.OnClickListener是Java中定义的SAM type,Kotlin支持SAM conversions

  

就像Java 8一样,Kotlin支持SAM转换。这意味着只要接口方法的参数类型与Kotlin函数的参数类型匹配,Kotlin函数文字就可以使用单个非默认方法自动转换为Java接口的实现。

假设您有一个用Java定义的接口:

public class Example {
    public interface SingleMethodInterface {
        int length(String text);
    }

    public static void set(SingleMethodInterface sam) {}
}

然后,您可以在Kotlin中通过以下两种方式调用set()函数:

//Passing a function type which accept a `String` and return an `Int`
val length: (String) -> Int = { it.length }
Example.set(length)
//or
Example.set { it.length }

//Passing an object which implements `SingleMethodInterface`
val length2: Main.SingleMethodInterface = object: Main.SingleMethodInterface {
    override fun length(text: String): Int {
        return text.length
    }
}
Example.set(length2)

简而言之,SAM转换提供了一种在Kotlin中编写干净代码的方法,该代码与Java交互。

答案 1 :(得分:3)

你的问题: 这些方法有什么区别?如果它们不同,哪一个更好,为什么?

编译之后,两者都会生成相同的字节码,但写入时会通过单行实现提供更多的可读性。

Java 8的强大功能是Lambda表达式。使用Lambda,您可以更简单地编写Java代码。这个功能略微改变了代码的丑陋外观。

示例:source

您可以将单一抽象方法(SAM)写为lambda。

如果您的界面只有一种方法。

public interface StateChangeListener {

    public void onStateChange(State oldState, State newState);

}

你可以像这样把它写成Lambda。

stateOwner.addStateListener(
    (oldState, newState) -> System.out.println("State changed")
);

但是这两种方法都是相同的,但你可以看到第二种方法非常简单并且删除了丑陋的实现。

在Kotlin中,lambda表达式与Java不同。

Kotlin lambda 表达示例:source

val add: (Int, Int) -> Int = { a, b ->  a + b }

上面的函数变量可以像这样调用:

val addedValue: Int = add(5, 5)

这将返回两个整数的附加值。

在这个例子中,您可以看到(Int, Int) -> Int,这在Kotlin中称为lambda函数。

所以Kotlin lambda和Java lambda函数完全不同。

您可以在Kotlin文档中看到:

  

就像Java 8一样,Kotlin支持SAM转换。这意味着   Kotlin函数文字可以自动转换为   使用单个非默认方法实现Java接口,   只要接口方法的参数类型匹配即可   Kotlin函数的参数类型。

实际上,您正在kotlin中编写lambda,稍后它将转换为java接口。所以两种方法都不同。但是当谈到执行时两者都是一样的。它不会影响编译时间,所以总是建议使用lambda。

希望有所帮助:)