lambda 和 高阶函数

之前学习了 lambda 和高阶函数,然后在 android 开发中对 onClick 事件进行监听是一个很常用的功能,kotlin 的常规实现如下:

    rootView.setOnClickListener { view ->println("点击了这个ID=${view.id}的view")}

然后在开发中不可避免的我们也要写一些自定义监听之类的代码。这个时候如果还用 java 的思想去实现的话就有点舍近求远了。

java 思想实现

在 java 中我们一般的做法是这样的

  • 定义一个接口
  • 定义一个接口类型变量
  • 定义一个 set 方法
  • 调用 set 方法设置接口的实现类

用 kotlin 实现就是如下

class MyView{//定义一个接口interface IOnLabelCheckedListener {fun onLabelCheck(label: String)}//定义一个接口类型变量private var onLabelChecked: IOnLabelCheckedListener? = nullprivate fun initView(context: Context) {view.setOnCheckedChangeListener { radioGroup, i ->onLabelChecked.onLabelCheck(radioGroup.findViewById<RadioButton>(i).text.toString())}}//定义一个 set 方法fun setOnLabelCheckedListener(e: IOnLabelCheckedListener) {this.onLabelChecked = e}
}// 调用set方法,通过匿名内部类实现MyView.setOnLabelCheckedListener(object : LabelBarView.IOnLabelCheckedListener {override fun onLabelCheck(label: String) {}})

这样实现的问题

当然是太复杂了。而且最初的时候这样写一时搞不明白为什么 MyView.setOnLabelCheckedListener 方法内部不能传入 lambda 表达式,lambda 表达式的存在不就是为了替代匿名内部类嘛。而且如果这个接口定义的是一个 java 类型的接口就是可以用 lambda 表达式的。这是为什么?最后猜想是因为 kotlin 在和 java 互相调用的时候中间又包裹了一层,而我们直接使用 kotlin 来定义这个接口不存在中间这一层,而我们定义的 set 方法又不是一个高阶函数,当然不能使用 lambda 表达式。

下面就用 kotlin 的思想来实现回调

使用高阶函数来实现

kotlin 和 java 有一个重要的不同就是函数式编程。在函数式编程的思想中函数是一等公民,在使用 kotlin 时我们要多利用这种思维来思考问题。Kotlin 中提供了高阶函数,它可以直接使用一个函数来作为返回值,对于习惯于 java 来编程的我来说刚开始理解起来有些困难,下面我把我一步一步的实现一个高阶函数的思路写下,希望对大家有所帮助。

首先,能想到的就是函数传递,要用 lambda 来替代掉匿名内部类可以这样来实现

//从最基础的开始做,把匿名内部类通过 lambda 实现
MyView.setOnLabelCheckedListener(object : MyView.IOnLabelCheckedListener {override fun onLabelCheck(label: String) {println(label)}
})
// 首先 MyView.IOnLabelCheckedListener 中只有一个方法 onLabelCheck(label: String)
// 因此可以写出 lambda 表达式如下
var lam: (String) -> Unit = { label -> println(label) }

然后,需要把写好的 lambda 传递进去,这个时候就要求 setOnLabelCheckedListener 方法是一个高阶函数

    // 这里接收一个 上面我们改造好的表达式 lam ,它内部实现应该是把 e 赋值给当前类的一个对象fun setOnLabelCheckedListener(e: (String) -> Unit) {this.lisenter = e}//显然 lisenter 就应该是这样的var linsnter: (String) -> Unit = {}

最后使用 linsnter 进行回调

    private fun initView(context: Context) {view.setOnCheckedChangeListener { radioGroup, i ->linsnter(radioGroup.findViewById<RadioButton>(i).text.toString())}}

最终代码结果:

class MyView{var linsnter: (String) -> Unit = {}private fun initView(context: Context) {view.setOnCheckedChangeListener { radioGroup, i ->linsnter(radioGroup.findViewById<RadioButton>(i).text.toString())}}fun setOnLabelCheckedListener(e: (String) -> Unit) {  this.lisenter = e}
}// 调用时将变量 lam 省略,直接使用一个表达式view.setOnLabelCheckedListener { label ->println(label)}

最终的代码和之前的代码有两个最大的不同,一是没有了接口定义,二是没有了匿名内部类。

更好的使用高阶函数

高阶函数的使用更多的时候能使我们的代码更简洁,比如下面这段代码:

    fun refreshData(e: ((Boolean, String) -> Unit)): Boolean {if (!UserInfoManager.getInstance().isLogin) {e(false, "未登录")return false}NETWorkUtils.request(ApiParamter(), object : ApiListener<ResponseData> {override fun onApiCompleted(data: ResponseData?) {e(true, "成功")}override fun onApiError(errorCode: Int, errorCodeMessage: String) {e(false, errorCodeMessage)}})return true}

那么在调用它的时候就可以这样:

     mView.refreshData { isSuccess, msg ->//do something}

是不是很简单,省去了再写一个接口。同时如果是用 java 来调用 refreshData 方法也一样可以的:

        mView.refreshData(new Function2<Boolean, String, Unit>() {@Overridepublic Unit invoke(Boolean aBoolean, String s) {// do somethingreturn null;}});

Kotlin 提供了一系列的 Function 接口类来供 java 调用高阶函数时使用,最多支持22个参数有兴趣的可以查看一下。

以上就是在 Kotlin 中使用高阶函数来替代传统的回调函数的方法。不对之处还请指正。


版权声明:本文为博主原创文章,转载请声明出处,请尊重别人的劳动成果,谢谢!

Kotlin 使用高阶函数实现回调相关推荐

  1. Kotlin使用高阶函数实现多方法回调

    最近项目中开始使用kotlin,遇到的一个问题就是从多方法回调的问题 常规的java回调如下: public interface OnCallBack<T> {void onSuccess ...

  2. Kotlin的高阶函数和常用高阶函数

    Kotlin的高阶函数和常用高阶函数 文章来源:企鹅号 - Android先生 高阶函数的定义 将函数当做参数或者是返回值的函数 什么是高阶函数 可以看看我们常用的 函数: 首先我们可以知道, 是 的 ...

  3. 高阶函数和回调函数的区别

    今天看到高阶函数的概念,突然就迷不过来了,这个高阶函数和回调有什么区别呢? 高阶函数英文叫Higher-order function.那么什么是高阶函数? 刚开始学习语言我最害怕看到这种XX函数的,一 ...

  4. 【Kotlin】Kotlin的高阶函数与Lambda表达式

    前言 Kotlin的高阶函数与Lambda表达式是Kotlin的两大特色,使用频率非常高.熟悉它的用法与本质对于简化代码.提升开发效率非常有帮助. 这两个概念不是同一个东西,但是又有非常紧密的关联.这 ...

  5. Kotlin 学习 高阶函数

    摘自第一行Android代码第3版 定义 如果一个函数接收另一个函数作为参数,或者返回值的类型是另一个和函数,那么该函数就称为高阶函数 // 语法示例 (String,Int) -> Unit ...

  6. kotlin 常用高阶函数

    package kotlinall.chapter5import java.io.BufferedReader import java.io.FileReader import java.lang.S ...

  7. Android开发基础——Kotlin:高阶函数

    高阶函数 如果一个函数接收另一个函数作为参数,或者返回值的类型是另一个函数,那么该函数就称为高阶函数. 同时Kotlin中还增加了函数类型的概念,因此如果将函数类型添加到一个函数的参数声明或返回值声明 ...

  8. 【kotlin】高阶函数详解

    文章目录 定义高阶函数 内联函数的作用 高级函数的应用 简化SharedPreferences 的用法 简化 ContentValues 的用法 定义高阶函数 如果一个函数接收另一个函数作为参数,或者 ...

  9. Kotlin常用高阶函数

    高阶函数 高阶函数可以把函数作为参数传递或者返回值返回的函数.既然函数对象作为数值进行传递那么就会有如何引用函数的问题.函数引用的三种方式: 直接双冒号的方式,引用的是包级别的函数: // 这种引用适 ...

最新文章

  1. 说到心里的哲理个性签名 学生时代的恋爱无非就是陪伴二字
  2. CSDN湘苗培优|火热报名中
  3. 通过setTimeout处理click,dblclick,mousedown等事件的冲突
  4. 推荐算法炼丹笔记:做向量召回 All You Need is 双塔
  5. 疫情期间用掉了1400亿个!二维码会被人类扫完吗?
  6. DNS 服务器地址大全
  7. string.Format 格式化
  8. [css] 为什么说css的选择器一般不要超过三级?
  9. 上海电力学院计算机技术,上海电力学院计算机与信息工程学院介绍
  10. FPGA实现低高速接口更新说明
  11. idea java mapper.xml文件sql黄色背景解决
  12. java泛型概念与通配符含义初探
  13. C语言在工业工程专业的应用,工业工程专业知识介绍
  14. 转帖-win2003各版本的区别
  15. 《无人机DIY》——导读
  16. 近义词替换-近义词替换器-免费近义词替换器
  17. Word插入特殊符号
  18. 解决FTP服务器FileZilla server中文乱码问题
  19. 横向浅析Small,RePlugin两个插件化框架
  20. 用html代码在word中插入分页符,Word文档中插入分页符并对分页方式进行设置的方法...

热门文章

  1. oracle erp技巧,Oracle ERP 使用者操作指南II(深入浅出系列).pdf
  2. 韩顺平集合课后作业Homework06.java探讨
  3. 5 年工作经验,容器与 Pod 的区别和联系都说不清,你敢信?
  4. Html合并单元格的使用
  5. FastReport实现预览
  6. 瓷砖 划痕检测matlab,六招教你修复瓷砖划痕,分分钟解决问题!
  7. 某211高校食堂饭菜价格贵得离谱惹争议!学生:吃不起饭了!
  8. Hive 2.1.1安装配置
  9. pyecharts安装
  10. 数据库事务介绍(二)如何使用事务