作者:晴天小庭
近些年声明式布局
开发方式逐渐从网页端延展到了手机端,说到底还是声明式太香了,其代码更加清晰、简洁,并且更接近于自然语言的表达方式。这使得代码易于理解和维护,降低了开发人员的心智负担。
谷歌和苹果分别维护着两个地球上最大的手机操作系统:Android和IOS。长期以来,由于编程语言的特性,手机端一直都是使用命令式布局(偏向面向对象的开发方式)来开发UI,但是随着手机UI逐渐复杂和动态化,原有的方式暴露了其瓶颈,越来越多的手机端工程师抱怨,实现产品要求的效果越来越难了。于是为了适应市场的要求,谷歌和苹果分别推出了原生的声明式布局
开发框架,苹果端是SwiftUi,安卓端就是本期的主角-Jetpack Compose
。
如果你从来没听说过Jetpack Compose
,笔者建议你先阅读一下官方的简介和开发文档,因为本期节目并不会从0开始介绍这个框架,而是带领新人攻克最难的几个入门门槛。
- Jetpack Compose 简介 | Android Developers (google.cn)
- Jetpack Compose 开发文档 | Android Developers (google.cn)
如果你已经大致读完了上面两个文档,你仍然回到这篇文章,那说明你遇到了笔者一开始遇到的问题:Jetpack Compose
的文档实在写的太烂了,充满了机翻,而且比较难的概念只是一笔带过。
本章会手把手带你理解Jetpack Compose初学最难理解的几个难点。
一、可组合函数与附带效应
可组合函数
是Compose中描述UI的函数,你可以把它类比成HTML,可组合函数使用kotlin作为开发语言。
关于可组合函数,必须有以下特点:
-
此函数带有
@Composable
注释。所有可组合函数都必须带有此注释;此注释可告知 Compose 编译器:此函数旨在将数据转换为界面。 -
此函数接受数据。可组合函数可以接受一些参数,这些参数可让应用逻辑描述界面。在本例中,我们的 widget 接受一个
String
,因此它可以按名称问候用户。 -
此函数可以在界面中显示文本。为此,它会调用
Text()
可组合函数,该函数实际上会创建文本界面元素。可组合函数通过调用其他可组合函数来发出界面层次结构。 -
此函数不会返回任何内容。发出界面的 Compose 函数不需要返回任何内容,因为它们描述所需的屏幕状态,而不是构造界面 widget。
-
可组合函数快速、幂等且没有附带效应。
- 使用同一参数多次调用此函数时,它的行为方式相同,并且它不使用其他值,如全局变量或对
random()
的调用。 - 此函数描述界面而没有任何副作用,如修改属性或全局变量。
- 使用同一参数多次调用此函数时,它的行为方式相同,并且它不使用其他值,如全局变量或对
这里出现了一个概念:幂等,也许有人第一次接触到这个词,我提供一下关于这个词的解释:
在编程中,"幂等"是指一个操作或函数,无论执行多少次,结果都是相同的。换句话说,对于给定的输入,多次执行相同的操作或函数不会产生额外的影响或副作用。
假设你的函数改变了外部的变量或者访问了外部的变量,那它就不是幂等的,例如下面的函数:
var a:Int=1
fun nonIdempotent(){
a++
}
很显然,每次调用nonIdempotent()方法的结果都是不一样的,这种就是"不幂等
"的函数。
相同的,我们再来看看幂等
的函数:
fun idempotent(a:Int):Int{
return a+1
}
如果我传入的a不一样,每次返回的结果都不一样,还算幂等吗?当然算,我们说幂等的前提是保持参数一致,如果参数一致的情况下,结果永远都是a+1,因此方法是幂等的。
下面再看一个函数,请问这是幂等的吗:
fun idempotentOrNonIdempotent(a:Int):Int{
print("${a+1}")
return a+1
}
也许你会觉得这是幂等的,因为结果是一致的,但是这个函数却是不幂等
的,因为print会对控制台输出日志,这属于对函数外部产生了影响,而对外部产生影响属于附带效应
,因此也是不幂等的。
附带效应
是指发生在可组合函数作用域之外的应用状态的变化。由于可组合项的生命周期和属性(例如不可预测的重组、以不同顺序执行可组合项的重组或可以舍弃的重组),可组合项在理想情况下应该是无附带效应的。
回到Compose中来,为什么Compose的可组合函数要强调幂等且没有附带效应
呢?因为Compose是没有对象这一个概念的,它是用纯粹的函数来表达UI,因此UI的刷新就是重新调用一次可组合函数
,刷新过程由Compose的智能重组
机制自动完成,关于这个机制我们接下来才会提到,你只需要了解一个概念:即Compose的UI刷新就是重新调用一次可组合函数,而且调用的次数和时机是不确定的
即可。
基于这个因素,如果我们的可组合函数里面出现了附带效应的情况,就会导致附带效应在不恰