专栏名称: 鸿洋
你好,欢迎关注鸿洋的公众号,每天为您推送高质量文章,让你每天都能涨知识。点击历史消息,查看所有已推送的文章,喜欢可以置顶本公众号。此外,本公众号支持投稿,如果你有原创的文章,希望通过本公众号发布,欢迎投稿。
目录
相关文章推荐
stormzhang  ·  真正该刺激的是收入 ·  昨天  
鸿洋  ·  一款高效的HarmonyOS工具包 ·  昨天  
鸿洋  ·  Android主线程锁监控的一种方案 ·  5 天前  
鸿洋  ·  Android多渠道打包指南 ·  6 天前  
鸿洋  ·  systemserver进程监控者--wat ... ·  1 周前  
51好读  ›  专栏  ›  鸿洋

Kotlin新特性:Context receivers将被废弃

鸿洋  · 公众号  · android  · 2024-08-16 08:35

正文

前言

在7月30日发布的Kotlin 2.0.20-RC版本特性中,主要强调了一些功能改进,如:

  • 支持2.0.20-RC 的 Kotlin 插件捆绑在最新的 IntelliJ IDEA 和 Android Studio 中。

  • Data Class copy()函数具有与构造函数相同的可见性。

  • 逐步废弃Context receivers特性。

  • Kotlin 跨平台以及Kotlin Native的一些改进。

其中对开发者而言较为重要的就是Kotin将逐步删除Context receivers特性。
1
关于Context receivers


Context receivers是在 Kotlin 1.6.20中版本中引入的,主要用来解决扩展函数只有一个上下文局限性的问题。

这个API虽然一直是实验性的,但是官方考虑到有很多开发者已经使用,所以Kotlin也不会在2.0.20版本中直接废弃,而是会逐步弃用,推荐使用Context parameters来代替,所以后续新功能我们就不要再使用Context receivers了。

当我们在2.0.20-RC版本中继续使用Context receivers时,编译器将会出现警告。

class MyContext

context(MyContext)
// warning: experimental context receivers are deprecated and will be superseded by context parameters.
// Please don't use context receivers. You can either pass parameters explicitly or use members with extensions.
fun someFunction() {
}

那我们可以怎么做呢?官方建议我们通过明确参数或者扩展成员函数的方式来实现。

明确参数

原代码如下所示:

context(ContextReceiverType)
fun someFunction() {
    contextReceiverMember()
}
修改后的代码如下所示:
fun someFunction(explicitContext: ContextReceiverType) {
    explicitContext.contextReceiverMember()
}


好家伙,这不又回到了传参的方式,当初介绍Context receivers优势时可也是这个例子 。

扩展成员函数

原代码如下所示:

context(ContextReceiverType)
fun contextReceiverMember() = TODO()

context(ContextReceiverType)
fun someFunction() {
    contextReceiverMember()
}

修改之后的代码如下所示:

class ContextReceiverType {
    fun contextReceiverMember() = TODO()
}

fun ContextReceiverType.someFunction() {
    contextReceiverMember()
}

接着我们来看看官方推荐的Context parameters是个啥?

2
关于 Context parameters


目前Koltin官方文档中还没有对Context parameter的介绍,我们只能从github链接中找到。里面的东西比较多,并且当前还不稳定,我们只来看如何声明Context parameter。

如何声明Context parameters

Context parameters 用 context 关键字声明,后跟一个参数列表,每个参数的形式名称为: Type,代码如下所示:

interface Type {
  context(analysisScope: AnalysisScope)
  val isNullable: Boolean = ...
}

context(analysisScope: AnalysisScope)
fun Type.equalTo(other: Type)Boolean = ...

context(_: AnalysisScope)
val Type.isBoolean: Boolean get() = this.equalTo(BuiltIns.Boolean)

同时属性也是支持Context parameters的,用法如下所示:

context(users: UserRepository)
val firstUser: User? get() = users.getById(1)

同时Context parameters也是隐式的,因为当调用带有Context parameters的函数或属性时,这些参数并不会被明确列出,如:

context(logger: Logger) fun logWithTime(message: String) =
  logger.log("${LocalDateTime.now()}$message")

context(logger: Logger) fun User.doAction() {
  logWithTime("saving user $id")
  // ...
}

从这里来看,感觉Context parameters和Context receivers没啥区别,可以说是写法变了而已,但是官方肯定会列出来一些优势,但是仍然不影响Context parameters以后被废弃。
3
思考


Context receivers这么快就被废弃是值得我们思考的,Context receivers当初解决的问题无非就是少声明一个参数的问题,是否有必要为了图一时之快而留后患。就像我们现在使用Kotlin语法糖一样,很多基础方法都忘了。

说了这么多,不得不感叹一句:幸亏我没用Context receivers。



最后推荐一下我做的网站,玩Android: wanandroid.com ,包含详尽的知识体系、好用的工具,还有本公众号文章合集,欢迎体验和收藏!


推荐阅读

一文看懂DecorView的一生
LeakCanary 你真的了解么?看看这些高级用法
详解Android14 Activity 启动过程


扫一扫 关注我的公众号

如果你想要跟大家分享你的文章,欢迎投稿~


┏(^0^)┛明天见!