美文网首页kotlin
Kotlin-那些好用的标准高阶函数

Kotlin-那些好用的标准高阶函数

作者: h2coder | 来源:发表于2020-08-15 09:59 被阅读0次

Kotlin特性总结的第二篇,上一篇我们谈了拓展函数和拓展属性。本篇我们来学习一下高阶函数。

拓展函数是对类的拓展,那么高阶函数是什么呢?

高阶函数定义:函数的参数是函数,或者返回值是函数的函数,就为高阶函数。

本篇讲解到的高阶函数都在Standard.kt文件中。用好这些高阶函数,有利于我们的kotlin代码可读性更强,更简洁。

曰:用Kotlin一时爽,一直用一直爽~

标准高阶函数有哪些?

run和T.run

  1. run函数和带T的T.run是2种高阶函数。

run函数需要传入的一个block闭包,闭包中的作用域是和括号外层一致的。返回值是block的返回值,所以可以作为一段代码块去处理,并返回一个结果。可以让我们的代码分层,而不像Java是堆在一块。

//定义
@kotlin.internal.InlineOnly
public inline fun <R> run(block: () -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}
  • 实践:

例如我们需要判断用户的类型,弹出不同的操作对话框,就可以将处理包裹在run方法中,并返回一个结果就是dialog。

//获取指定id用户的用户信息
val userInfo = LoginService.getUserInfo(userId)
//判断是否是上麦用户
val isSeatUpUser = userInfo.isSeatUpUser()
val dialog = run {
    if(isSeatUpUser) {
        //上麦用户
        SeatUpUserOperationDialog()
    } else {
        //普通用户
        RoomUserOperationDialog()
    }
}
//省略一些,dialog配置
dialog.show()
  1. T.run,是对T类型的一个拓展方法。它和上面的run()不一样的地方是作用域不同,同样接收一个block闭包,并且this作用域是拓展的类,即为T,这样的好处是,可以直接获取T类中的属性。
//定义
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}
  • 实践:

我们经常使用的RecyclerView的Adapter,在onBindView中对模型进行取字段设置到条目控件中,如果是java我们对model做各种get操作。kotlin的T.run()拓展可以直接解开模型直接取属性使用,让我们的代码更简洁。

override fun onBindViewHolder(holder: ViewHolder, itemModel: FreeConsultModel.ListModel) {
    itemModel.run {
        //头像设置
        holder.vAvatar.loadUrlImageToRound(avatar)
        //昵称设置
        holder.vName.text = nickname
        //消息内容设置
        holder.vMsgContent.text = text
        //消息日期设置
        holder.vDate.text = createTime
    }
}

T.with

with高阶函数,和上面的T.run()拓展不一样,T.run()是直接将作用域作为调用方T,而with中作用域是由传入的receiver对象作为作用域,同时传入一个闭包,闭包内的this则为receiver。所以也可以直接解出receiver的属性进行使用,返回值为block的返回值。

//定义
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return receiver.block()
}
  • 实践:

相信我们对RecyclerView的使用已经熟烂如心了,配置LayoutManager、配置Adapter,还有一些滚动监听等,使用with()高阶函数,我们可以对传入的RecyclerView进行配置操作。

with(vRecyclerView) {
    layoutManager = LinearLayoutManager(context)
    adapter = RAdapter(List<UserModel>())
}

T.let

let高阶函数,对T类型进行拓展,接收一个T类型参数的block,返回block的返回值。let和run很相似,但是run中作用域是直接使用this,而let则是将传入参数作为一个为it的参数(默认的,可以手动指定别的名字)

@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}
  • 实践:

模型级联非空判断和非空执行闭包,相比java的逐层!=null判断,kotlin优雅了许多。

//调用使用ARouter注入的登录服务,跳转到登录页面,由于我们使用组件化开发,可以单独运行,所以LoginService可能会找不到,而为null,所以需要判空,我们就可以使用let,调用前加一个?号,则代表不为空时才进入到闭包中。
mLoginService?.let {
    it.goLogin(activity)
}

//模型解包非空判断
model.data?.list?.let {
    //一路走来,获取到模型中的list属性,我们一般会添加到列表的数据集中再更新列表
    mListItem.addAll(it)
    mListAdapter.notifyDataSetChange()
}

T.also

also高阶方法,和let很类似,区别是let最后的返回值是block闭包中的返回值,而also则是返回自身。如果需要最后返回值为自身,则可以使用also。

//定义
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block(this)
    return this
}
  • 实践:

例如,我们已有一个文件路径,我们需要创建文件前,先创建好文件夹,则可以先使用let创建File文件,再使用also进行文件夹创建,最后返回一个File文件。

//普通函数
fun makeDir(filePath: String): File  {
   val file = File(filePath)
   file.mkdirs()
   return file
}

//also改造
val file = filePath.let {
    File(it)
}.also {
    it.mkdirs()
}
//file处理

T.apply

apply高阶函数,对T类进行拓展,接收一个T的拓展闭包,和also很像,但是also接收的闭包的T是作为参数传入的,所以使用it来使用,而apply传入的闭包是自身的拓展,所以直接是this就可以访问,可以调用自身属性和方法。

@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}
  • 实践:

一般我们列表页面,会有一个标题栏TopBar,一个下拉刷新、下拉加载更多的刷新布局等控件,而我们对他们的相关配置就可以使用apply来包裹。

//顶部栏配置
vTopBar.apply {
    setTitle(R.string.mine_main_system_announcement)
    addLeftBackImageButton().click {
        activity?.finish()
    }
}
//下拉刷新、上拉加载布局配置
vRefreshLayout.apply {
    setOnRefreshListener {
        refresh()
    }
    setOnLoadMoreListener {
        loadMore()
    }
}
//列表控件配置
vRefreshList.apply {
    layoutManager = LinearLayoutManager(activity)
    adapter = mListAdapter
}

高阶函数那么多,怎么选择?

下面的图是搜索到其他博客中的,总结得很好,这里也参考一下。

kotlin标准高阶函数图表.png

总结

Kotlin提供了众多的高阶方法,合理使用会让我们的代码更整洁、简洁,可读性更强,如果不知道使用哪个高阶方法可以参考上图。

相关文章

  • Kotlin-那些好用的标准高阶函数

    Kotlin特性总结的第二篇,上一篇我们谈了拓展函数和拓展属性。本篇我们来学习一下高阶函数。 拓展函数是对类的拓展...

  • kotlin从入门到看开 ₆

    layout: posttitle: "kotlin-高阶函数"subtitle: "这个世...

  • Kotlin-高阶函数的使用(二)

    文章目录: Kotlin-高阶函数的使用(一) 上一篇文章带大家认识到了什么是高阶函数,那这一章就带大家看看高阶函...

  • Kotlin使用技巧(一)-接口与命名参数的优雅运用

    抛出问题 看过我的Kotlin-高阶函数的使用(二)都知道,我们的setOnClickListener可以这样写:...

  • Kotlin-高阶函数

    函数入门 今天我们来讲解Kotlin的函数一说到函数,很多同学可能脑子里面是这样的一个概念。 我们高中数学经常与函...

  • Kotlin-高阶函数

    介绍 Kotlin是函数式编程,所以可以把函数作为参数传递给函数,或者作为函数的返回值使用,我们称其为高阶函数。本...

  • kotlin-高阶函数

    定义:一个用函数作为参数或者返回值的函数如何定义:()->Unit 括号里面代表函数的参数,箭头后面代表函数的返回...

  • Kotlin-高阶函数

    高阶函数的作用 就是用来定义函数式编程里面接收Lambda表达式的函数。 高阶函数的定义 如果一个函数接收另一个函...

  • Kotlin-标准函数

    什么是标准函数?是指在Standard.kt文件中定义的函数,在任何的Kotlin代码都可以自由地调用。 1.le...

  • Kotlin-标准函数

    1、标准函数with 1.1、Kotlin中的标准函数指的是Standard.kt(emmm...虽然可能并没多大...

网友评论

    本文标题:Kotlin-那些好用的标准高阶函数

    本文链接:https://www.haomeiwen.com/subject/hdvndktx.html