前言

Jetpack Compose 是用于构建原生界面的「新款 Android 工具包」。2021 Google IO 大会上,Google宣布:「Jetpack Compose 1.0 即将面世」。

作为Android未来新的UI开发标准,Compose 会为 Android 开发带来哪些变化呢?本文将带来Jetpack Compose的特点及其跟传统Android UI开发方式的分析:

  1. 基于Kotlin

  2. 声明式开发

  3. UI刷新机制

  4. 状态管理

  5. UI组件类型

  6. 实时预览

  7. 兼容性

  8. Jetpack Compose 与 Flutter的关系


基于Kotlin

现行的 Andoird 开发体系:Java + xml,但近年来 Google已经宣布Kotlin是Android开发的第一语言。Jetpack Compose这套声明式UI采用的底层DSL是Kotlin,即 你在使用Jetpack Compose开发UI时,实际上是使用Kotlin进行UI开发,「即 完全统一了Android开发语言。」


声明式开发

现行的 Andoird 视图体系属于传统的命令式开发方式:使用XML布局、通过 findViewById 获取控件的引用,命令式地更新状态、刷新UI。命令式UI开发的特点是:

  • UI可变:接受命令后通过变化自身刷新UI

  • UI持有状态State:控件的变化通过改变自身状态实现

Jetpack Compose使用的是声明式UI开发方式,其特点相对于命令式UI开发有较大区别:

  • UI不可变 : @Composable函数不返回任何可引用句柄,无法被外界改变;

  • UI不持有State: @Composable函数无法持有状态,显示的数据都需要通过参数传入;

总的来说,Jetpack Compose进行声明式UI开发时:

  1. 每个UI绘制会一个“纯函数”的方式运行;

  2. 当 状态State 变化时函数重新执行刷新UI。


UI刷新机制

Jetpack Compose刷新UI的方式叫重组,即使用新数据再次调用UI绘制的函数。

@Composable
fun ClickCounter(clicks: Int, onClick: () -> Unit) {
    Button(onClick = onClick) {
        Text("I've been clicked $clicks times")
    }
}

如上述按钮设置:每次点击该按钮时,调用方都会更新 clicks 的值。Compose 会再次调用 lambda 与 Text 函数以显示新值。

当数据变化时就会触发重组,如果每次都全量重组则会带来很多性能损耗。「类似React那种声明式UI, 每次绘制时都会通过diff算法精准更新 DOM从而实现局部刷新,最终保证React的刷新性能。」

Jetpack Compose 为了保证重组性能才使用了类似的思想:「局部刷新,也叫智能重组」。原理是:在 Gap Buffer 这样线性结构上进行 diff。

「Gap Buffer 是一个树形结构经 DFS 处理后的数组」,数组单元通过 key 标记其在树上的位置信息。Compose 在编译期为Composable 生成带有位置信息的 key存入到 Gap Buffer 数组的对应位置。运行时根据 key 来识别 Composable 节点是否发生了位置变化,最终决定是否参与重组。同时,「Gap Buffer 还会记录 Composable 对象关联的状态(State 或 Parameters)」:仅当关联状态变化时,Composable 才会参与重组。


状态管理(State)

Jetpack Compose的UI变化本质是:「状态(State) 驱动」,即控件UI的变化原因是控件UI的状态发生了变化。

对于传统的UI开发模式,状态(State) 只是UI控件的一个属性,仅此而已。


UI组件类型

虽然Jetpack Compose 1.0 才刚面世,但实际上其UI组件库已经十分完备,几乎完全覆盖了Android现有视图系统的所有组件及能力,主要包括:

  • 基础UI组件,如Button、TextView等,连Card、Fab、AppBar等Material Designe的控件都会涵盖;

  • 列表类组件,如List等,采用items{...} 中创建每条项目的 Composalbe,避免了额外的Adapter适配;

  • 布局类组件,提供了多种容器类Composalbe,可以十分高效方便地对子组件进行布局;通过一系列链式调用的Modifier操作符来装饰 Composable 的外观。操作符的使用十分丰富,如size、backgrounds、padding等;

  • 动画组件,同样是采用状态(State)驱动进行动画效果的实现。


实时预览

Jetpack Compose 能做到开发过程中的「实时预览」,预览机制可以做到与真机无异,真正的所见所即得。


兼容性

Jetpack Compose 可以与Android现有的视图View开发体系一起兼容使用,即不一定是新有项目才使用Compose,「而是可以对已有项目引入Compose。」


Jetpack Compose 与 Flutter的关系

同属于UI开发框架,二者都是采用「声明式UI开发」,但二者并不存在互斥或者竞争关系。

因为:「Jetpack Compose存在于Android的原生UI绘制体系、Flutter主要还是应用于跨平台的UI绘制范畴内。」

但二者都是代表未来Android UI绘制的开发方向:「声明式UI开发」。


展望

  • 正式发布:Compose 1.0 会在今年的7月正式发布,同时后续Android Studio 也将同步支持 Compose 开发。

  • 功能库支持越来越丰富:越来越多的 Jetpack 官方库以及常用的三方库开始加入对 Compose 的支持

  • 生态完善:Jetpack Compose目前不仅应用于Android客户端,同时最近也有Compose-Desktop、Compose-Web 等项目的发布,为 Compose 提供跨平台的能力,完善了整个Jetpack Compose的UI应用生态。


学习指南

1. 官方学习资料

https://goo.gle/compose-pathway https://goo.gle/compose-samples https://goo.gle/compose-docs

2. 中文学习项目

https://docs.compose.net.cn/


Jetpack Compose 1.0 终于要投入使用了!的更多相关文章

  1. Jetpack Compose What and Why, 6个问题

    Jetpack Compose What and Why, 6个问题 1.这个技术出现的背景, 初衷, 要达到什么样的目标或是要解决什么样的问题. Jetpack Compose是什么? 它是一个声明 ...

  2. Jetpack Compose学习(1)——从登录页开始入门

    原文地址:Jetpack Compose学习(1)--从登录页开始入门 | Stars-One的杂货小窝 Jetpack Compose UI在前几天出了1.0正式版,之前一直还在观望,终于是出了正式 ...

  3. Jetpack Compose和View的互操作性

    Jetpack Compose Interoperability Compose风这么大, 对于已有项目使用新技术, 难免会担心兼容性. 对于Compose来说, 至少和View的结合是无缝的. (目 ...

  4. Android Kotlin Jetpack Compose UI框架 完全解析

    前言 Q1的时候公司列了个培训计划,部分人作为讲师要上报培训课题.那时候刚从好几个Android项目里抽离出来,正好看到Jetpack发布了新玩意儿--Compose,我被它的快速实时打包给吸引住了, ...

  5. Android全新UI编程 - Jetpack Compose 超详细教程

    1. 简介 Jetpack Compose是在2019Google i/O大会上发布的新的库.Compose库是用响应式编程的方式对View进行构建,可以用更少更直观的代码,更强大的功能,能提高开发速 ...

  6. Jetpack Compose学习(2)——文本(Text)的使用

    原文: Jetpack Compose学习(2)--文本(Text)的使用 | Stars-One的杂货小窝 对于开发来说,文字最为基础的组件,我们先从这两个使用开始吧 本篇涉及到Kotlin和DSL ...

  7. Jetpack Compose之隐藏Scaffold的BottomNavigation

    做主页导航时会用到底部导航栏,Jetpack Compose提供了基础槽位的布局Scaffold,使用Scaffold可以构建底部导航栏,例如: @Composable fun Greeting(vm ...

  8. Jetpack Compose学习(3)——图标(Icon) 按钮(Button) 输入框(TextField) 的使用

    原文地址: Jetpack Compose学习(3)--图标(Icon) 按钮(Button) 输入框(TextField) 的使用 | Stars-One的杂货小窝 本篇分别对常用的组件:图标(Ic ...

  9. Jetpack Compose学习(4)——Image(图片)使用及Coil图片异步加载库使用

    原文地址 Jetpack Compose学习(4)--Image(图片)使用及Coil图片异步加载库使用 | Stars-One的杂货小窝 本篇讲解下关于Image的使用及使用Coil开源库异步加载网 ...

随机推荐

  1. 区分DDD中的Domain, Subdomain, Bounded Context, Problem/Solution Space

    区分DDD中的Domain, Subdomain, Bounded Context, Problem/Solution Space 译自: Domain, Subdomain, Bounded Con ...

  2. 1、centos7修改网卡名称为传统的eth0

    [root@localhost ~]# cd /etc/sysconfig/network-scripts/ [root@localhost network-scripts]#mv ifcfg-ens ...

  3. POJ 2236 Wireless Network 第一次做并查集,第一次写博客

    题意是判断两台电脑是否能通讯,两台修好的电脑距离在指定距离内可直接通讯,且两台修好的电脑能通过一台修好的电脑间接通讯.代码如下: #include <iostream> #include ...

  4. Linux系统下安装MongoDB

    下载安装包 去MongoDB官网https://www.mongodb.com/try/download/community,下载社区版的安装包: 我的Linux系统是CentOS 7.5版本的,通常 ...

  5. linux进程后台运行的几种方法 - nohup/setsid/&

    linux进程后台运行的几种方法 - nohup/setsid/& [转载]   我们经常会碰到这样的问题,用 telnet/ssh 登录了远程的 Linux 服务器,运行了一些耗时较长的任务 ...

  6. uni-app app端 人脸识别

    在听到人脸识别,哇塞!感觉来个个高大上的,去阿里 腾讯 看他们的人脸识别方法,官方sdk什么的. 到后来,需求确定了,拍照(照片)上传,后台去识别是不是本人,这一瞬间从天堂到地狱,放着官方那么好的方法 ...

  7. 第十一章:random库概述

    random库是使用随机数的python标准库 伪随机数:采用梅森旋转算法生成的伪随机序列中的元素 random库主要用于产生随机数 使用random库:import random random库的概 ...

  8. Js中关于构造函数,原型,原型链深入理解

    在 ES6之前,在Javascript不存在类(Class)的概念,javascript中不是基于类的,而是通过构造函数(constructor)和原型链(prototype chains)实现的.但 ...

  9. 脱离OBDeploy工具,手工部署OceanBase方法

    [简介] OBDeploy是OceanBase集群部署的工具,可以通过简单的几行命令,就能快速的进行OceanBase部署.但对于初学者来讲,可能会比较困惑,Deploy到底做了哪些事情?里面的具体步 ...

  10. C语言:逻辑运算符||

    #include <stdio.h> //逻辑运算符||特点:左右两边的表达式先做左边,如果左边为1则右边不用执行,整个结果为1:如果左边为0,再执行右边: main() { int x= ...