【问题标题】:Difference between OnclickListener methods in KotlinKotlin 中 OnclickListener 方法的区别
【发布时间】:2018-02-27 18:32:32
【问题描述】:

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

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

实现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 的。但是我无法正确理解这些方法。

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

【问题讨论】:

    标签: android kotlin


    【解决方案1】:

    它们引用相同的函数,但以不同的方式编写。第一种是调用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 互操作的干净代码的方法。

    【讨论】:

    • 很好的信息人,但你的例子与他的问题无关。
    • @Bhuvanesh Bs 我添加的示例用于解释SAM转换。
    • 感谢@BakaWaii 分享这些好信息。
    • 当然是 IntelliJAmiya,再次感谢@BakaWaii。对于这个出色的答案。理解 Kotlin 编程结构对我有很大帮助。
    • @Vikas Tiwari 欢迎您。我也在发现 Kotlin。对于这个问题,我认为有人可以给出更明确的答案。
    【解决方案2】:

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

    编译后,两者都会产生相同的字节码,但在编写时,单行实现会让您更具可读性。

    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。

    希望对你有帮助:)

    【讨论】:

    • 他询问了 lambda 方法和普通方法的区别。请更新您的答案@Intellij Amiya
    • 谢谢你回答@IntelliJAmiya。这对我理解有很大帮助。 setOnClickListener 转换
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    • 1970-01-01
    • 2020-04-09
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    • 2021-01-05
    相关资源
    最近更新 更多