查看原文
其他

Kotlin新特性:Context receivers将被废弃

鸿洋
2024-08-30

The following article is from Android技术圈 Author 黄林晴

前言

在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^)┛明天见!

继续滑动看下一个
鸿洋
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存