稀有猿诉

十年磨一剑,历炼出锋芒,说话千百句,不如码二行。

Jetpack Compose Road Map

Jetpack Compose是由Google在2019年Google I/O大会提出的新一代声明式UI框架,它基于Kotlin编程语言与Android Studio可以无缝衔接,在Google的大力推动下,现在已经变成了Android App的标准UI构建方式。网络上更是更是满屏的相关内容,如果说没有用过Compose都不好意思说自己会Android开发。是时候恶补一下了。

快速上手体验

可以follow下Google官方的Quick start教程来快速体验一下。

可以参考官方文档以进一步了解。

理解Compose

全用代码撸UI

体验过Compose可以发现,它与原生的Android app UI开发完全不同,最大的区别就是全是Kotlin代码,不用再去摆弄xml了。

本质是DSL

其实Compose与Kotlin最初搞的anko是类似的东西,它的核心是利用Kotlin的语言特性来实现了一套写UI的DSL。在Compose里面所有的花括号其实都是一个函数,而且Compose里面的DSL都是用的大写字母开头的驼峰式,如Text {},让人误以为这是一个类,但其实它是一个函数,容易让人误解不说,还不符合Kotlin语言的开发规范。这一点上当初的anko就相当的好,它的DSL命令都与函数的命名是一致(小写开头的驼峰式)。

注意,如果Compose用起来感觉相当的别扭,这说明缺少前置知识,要把Kotlin的一些高级特性熟悉一下,比如DSL,委拖机制以及扩展函数,只有把这些概念熟悉了以后,再写Compose会顺手很多。记住,Compose里面的所有东西都是函数调用,当成函数来写就可以了。

Compose其实就是一坨DSL,一层层的嵌套,本质上是一坨函数调用。极容易写出『箭头式』的代码,如这种:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Composable
private fun Greetings(
    modifier: Modifier = Modifier,
    names: List<String> = List(100) { "Compose #${it + 1}" }
) {
    // A surface container using the 'background' color from the theme
    Surface(modifier, color = MaterialTheme.colorScheme.background) {
        LazyColumn(modifier.padding(vertical = 4.dp)) {
            items(items = names) {
                 Greeting(it)
            }
        }
    }
}

当view的嵌套比较深的时候,更明显,这就需要我们要及时的抽出公共的Composable组件,其实就相当于抽出函数,以让嵌套不那么深。

其实Android的原生UI开发方式(也即View与xml)是相当强大的,特别是在复用,如animation,drawable,color,string和dimens的复用和适配已经相当完善了。这方面Compose还是略显笨拙,因为还必须代码,甚至还可能重复的代码。对于常规的页面,比如列表(横竖或者格子)和基础UI组件(图片,文字和按扭)组合而成的页,用Compose是完全不成问题的。但对于成百上千个各种小组件时,View的结构与交互都非常复杂的页面时,如某宝某东某团的页面,或者页面有重型的组件,如Webview,如video,graphics或者游戏,Compose肯定 力不从心。这也是为何国内,特别是一些大厂其实对Compose这玩意儿并不怎么感冒,真正在产品里使用的可能还是那些国外头部app。

到处是函数

Compose是用函数式编程方法,所有的Composable都是顶层的函数,也即是定义在类外面的函数,通常称为顶层函数。

标准库以及Material库中提供的所有轮子也都是函数,虽然它们的名字是大写的驼峰式,看起来像类一样,但其实它们都是函数。所有的Composable都接收尾部lambda,它其实是函数的最后一个参数,接收的是类型为Composable的函数,因此可以用尾部lambda的方式来实现这个参数。

还有一点就是,很多参数接收的也是一个函数,比如像接收Icon和Text的地方,其实是一个函数,而并不是直接把具体对象传过去,像这些地方的参数实际上需要的是一个能产生目标对象的Producer。这也是标准的函数式编程思想,也就是说尽可能的传递函数而非对象,目的在于这样更为灵活,可以让参数的使用尽可能的延时生成对象,也就是仅当真实需要的时候才会运行这个函数生成对象。而在中间过程中,或者说假如出错了,进入到错误显示的逻辑或者直接退出 了,那么其实就不需要生产对象了。

而传统的OO方式,是在构建流程的一开始就把对象创建好,并作为参数传过去,但其实可能完全没有必要。

进阶之路

最好的资源莫过于官方推出的教程。 jetpack compose course是Google官方推出的一系列教程,有视频讲解,有实战codelab,还有测试quiz。相当的丰富,可以看得出Google对Compose还是相当上心的。

项目实战

有一些非常优秀的真实的用Compose构建 出来的App可以供学习和参考,有些是官方的,有些则是民间的,不但开源,而且还有配套的博客来说明构建 的过程,是非常难得的参考 资料。

参考资料

Comments