Jetpack Compose | 声明式 UI 编程的革命

8,482 阅读6分钟

一、创建 Jetpack Compose 项目

1.下载 AndroidStudio

下载地址 developer.android.google.cn/studio/prev… ,这里下载的是 2020.3.1 版的AndroidStudio 。


2.创建 Compose 项目

AndroidStudio 中选择新建项目 New Project


你可以看到预览版的 Empty Compose Activity,选择此栏可以创建一个空的 Compose 项目。


然后填写一下项目的基本信息,本项目是 ComposeUnit


3.运行项目

经过一系列的自动下载和构建后,点击运行后,界面如下:


二、初始 Jetpack Compose 项目结构

1.目录结构

其实项目结构本身和普通的 AndroidStudio 项目并没有什么区别,都是根据 gradle 构建的 Android 项目。


在目录结构上,最大的不同点是在 res 目录下,你看不到 layout 布局文件了。不禁感叹, Android 十几代的风风雨雨,一直未能撼动 xml 布局大人的尊位。如今 Compose 的到来,仿佛揭竿而起,宣布着: “大人,时代变了....." .


2. gradle 与相关依赖

默认创建的项目 gradle 版本为 6.8.2


com.android.tools.build 版本为 gradle:7.0.0org.jetbrains.kotlin 版本为 1.4.30,官网说这个版本需要 1.4.21 及以上。


根据这些 gradle 配置,不在预览版的 AndroidStudio 中你也可以玩 Compose


3.源码结构

目前源码中只有 MainActivity.kt 文件,以及 ui.theme 中的一些主题相关文件。下面就来看看源码中进行了哪些操作吧。


三、初始 Jetpack Compose 项目源码简看

1. MainActivity.kt

在 Android 中,首先自然要看入口的 Acrivity。在AndroidManifest.xml 文件中可以看出,入口的 AcrivityMainActivity


首先要明白,是谁革了 xml 布局大人 的命。在 Activity 中必须要设置 View 才能进行展现,这里 AppCompatActivity 还是曾经那个androidx.appcompat.app 包中的 AppCompatActivity,他是清白的。


接下来看到 setContent 方法,就已经叛变了。如下代码,可以看出他是 AppCompatActivity拓展方法。如果你不了解 Kotlin,看到一堆的 {},估计会抓狂。在源码中可以看出, setContent 方法的第二个入参是一个函数对象,Kotlin 语法规定:如果函数的最后一个入参是函数对象,则可以写在() 外侧,如果() 中无参数,则 () 可省略。所以这里可以确定后面的 ComposeUnitTheme 那一坨本质上是一个函数对象。


2. 应用主题 ComposeUnitTheme

如下是 ui.theme.Theme.kt 中的代码,其中定义了一个 ComposeUnitTheme 的方法,看到方法和参数的命名也是醉了,竟然开头是大写的,这也许是为了更好地区分而违背命名规范吧。可以看到 ComposeUnitTheme 方法中被 @Composable 注解,在 setContent 第二入参中也有 @Composable 注解。从这里可以看出一点端倪,也许在 Compose 中并没有类似于 Flutter#Widget 的类,对标的是 @Composable 的注解方法。

private val DarkColorPalette = darkColors(
        primary = Purple200,
        primaryVariant = Purple700,
        secondary = Teal200
)

private val LightColorPalette = lightColors(
        primary = Purple500,
        primaryVariant = Purple700,
        secondary = Teal200
)

@Composable
fun ComposeUnitTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable() () -> Unit) {
    val colors = if (darkTheme) {
        DarkColorPalette
    } else {
        LightColorPalette
    }

    MaterialTheme(
            colors = colors,
            typography = Typography,
            shapes = Shapes,
            content = content
    )
}

上面的 ComposeUnitTheme 中有两个入参 darkTheme被 @Composable 标识 的函数对象。如下,在调用时可以传入参数,就表明使用 darkTheme ,而且不难分析出 Surface 也是 被 @Composable 标识 的函数。


可以跟进看一下,他是 androidx.compose.material 中提供的 @Composable 方法,它最后的入参仍是 被 @Composable 标识 的函数对象。如果这里把 content 改为 child ,估计你可能会会心一笑。


最后传入的是 Greeting("toly") 这个 被 @Composable 标识 的函数。括号里的入参会被 Text 接收。

也不难猜到 Text 本身也是一个 被 @Composable 标识 的函数。被定义在 androidx.compose.material 中。

所以现在我应该可以把 被 @Composable 标识 的函数 ≈ 组件 了吧。官方会给一些内置的组件使用,如 ScaffoldColumn RowImageText 等,而自定义组件就相当于自定义一个 @Composable 注解 的方法。这样和 Flutter 的用法比较一下,可以感觉这很 Flutter


3.关于预览

Flutter 的一个非常方便的功能是热重载,代码中的改动,能够很方便的同步到设备中。Compose 貌似并没有这样的功能,不过在右侧可以打开预览面板,在 DefaultPreview 注解下的组件可以被预览,预览界面在更改时可以同步。感觉不然 Flutter 强大,但有这,也不错,比不断重启要好。但 Flutter 不支持预览,也挺尴尬,两者半斤八两吧。


四、 Jetpack Compose 的革命

估计到这来,就开始有好事者来比较 FlutterCompose 哪个好,问该学哪个。Flutter 会不会被 Compose 替代?张风捷特烈 都在看 Compose 了 ,Flutter 是不是要凉了? Compose 有没有未来,compose 的组件是基于 Kotlin 的方法,Java 会不会被 Kotlin 彻底取代?我只想说:给爷滚!

首先 Compose Flutter 是同一革命阵营的战友,要清楚他们革的是谁的命,革的是命令式的 UI 编程,革的是 xml 布局大人 的命。有了 Flutter 的基础,对 Compose 的上手会更快一些,理解上也会更深刻,如果直接从命令式 UI 编程直接到 Compose ,你将经历一种思想的转变,这无论是去学 Flutter 还是 Compose 都无法避免的,思想这东西,别人是很难灌输给你的。

其次两者的定位不同, Compose 目前而言 ,只是针对 Android 的声明式 UI 工具包。而 Flutter 是跨平台,如今可以说在跨平台中已经小有成就。 Compose 也许未来会朝着跨平台发展,但 Flutter 近水楼台先得月,经过两年多的发展,已具备 天时、地利、人和 ,移动端的生态已经比较完善了。

对于 Compose 的未来发展,重点还是看生态。希望 Compose 稳定版可以早日到来,我就可以挥泪高呼:"再见了,xml 布局大人"。到时 ComposeUnit 项目定当献上,为您布道送行。Compose Kotlin 加持,还是 声明式 UI , 我还是很感兴趣的,当然在我心里 Flutter 是永远滴神 。至于问 Java OR Kotlin 的,都 2021 年了,您老还不会 Kotlin ?

最后想要说一句,既然是 革命,必定会有一批顽固派摇摆不定或进行阻挡。其实也理所应当,利益相关,谁也不想跳出自己的舒适圈,去到另一个不精通的地域去发展,或去涉足一个前途未卜的方向。也并不是所有的 革命都会成功,不是所有的先驱都会留名。但变革一定会产生思想层面的影响。就像戊戌变法百日维新,新的思想一旦萌发,旧的体系和制度终将没落。