JetPack Compose入门知识

1. Jetpack Compse是什么

Jetpack Compose 是Android新一代UI开发框架,采用声明式开发范式,开发者只需要将注意力放在如何编写UI界面上,当需要渲染的数据发生变化时,框架会自动完成UI刷新,其次它使用Kotlin DSL来编写API,相对于传统的试图开发方式来说,代码的效率更高,并且实现同样的功能只需要以前一半的代码量。可能有读者会说,有些项目就是使用以前的XML+View的方式来开发的,项目比较大,总不能全部用Compose重写一遍吧,这个其实不用担心,因为Compse有良好的兼容性,可以和AndroidView系统的传统代码共存,开发者可以按照自己的节奏去逐步过渡到Compose。这点和Vue.js的设计有点像。

2. 命令式UI和声明式UI的区别

命令式和声明式是两种截然不同的编程范式,命令式使用命令的方式去告诉计算机如何去做事情,计算机通过执行命令得出最终的结果,而声明式式直接告诉计算机想要的结果,计算机自己去想该怎么做

Android目前的View视图体系就是命令式编程范式,我们使用XML定义的布局是静态的,无法更具响应状态自行更新。开发者需要findViewById等获取视图对象,然后通过命令式代码调用对象方法刷新UI,而Compose采用的是声明式编程范式,我们只需要根据UI状态描述UI,当状态变化时,UI会自动更新。

这时可能会有人说,Data Binding不是可以让XML根据UI状态的变化更新吗?确实是,Data Binding就是Compose诞生之前的一种声明式UI方案,但是感觉用起来还是比较复杂。而且性能不高,因为需要去和XML交互,但是Compose只依赖Kotlin一种语言,避免了因为语言之间的交互带来的性能开销以及安全问题。而且Compose UI的Composable通过Kotlin的尾Lamda语法特性让Composable之间可以嵌套,形成Composeable的树形层级,UI表达能力并不比XML的低

3.Compose API 的设计原则

由于Compose在编程范式和传统视图体系有着根本的不同,所以我们开始学习它之前,需要对Compose API的设计原则做一个介绍。然后开发的时候应该要严格遵守这些原则,这样代码的可维护性才会更高

3.1 一切组件都是函数

Compose声明式UI的基础是Compose函数,Composeable函数通过多级嵌套形成结构化的函数调用链,函数调用链经过运行后生成一棵UI视图树。

视图树一旦生成便不可随意改变。视图的刷新时依靠Composeable函数的反复执行来实现的,当需要显示的数据发生变化时,Composeable函数基于新参数再次执行,更新底层视图树,最终完成视图的刷新

在这里插入图片描述 在Compose里,一切组件都是函数,不会有继承的层次结构,所有组件都是顶层函数,在Kotlin规范中要求函数名的首字母小写,而在Compose中推荐使用首字母大写,而且不允许有返回值,这样在DSL中书写时可读性更好

3.2 以组合代替继承

在设计模式中我们都知道,组合优于继承,Android的传统视图系统中的所有组件都是直接或者间接的继承自View类,TextView继承自View,而Button又继承自TextView,这导致了处于末端的View继承了太多无用的功能,所以出现了“Button上的文字可以复制”,而Composable作为函数没有继承关系,有利于促使开发者使用组合的视角去思考问题。

Compose的视图树使用组合

在这里插入图片描述


传统的View视图树使用的是继承 在这里插入图片描述

Compose的组合的方式让组件的职责更加单一

3.3 单一数据源

单一数据源是包括Compose在内的声明式UI框架中的重要原则,我们可以回想下EditText,它的文字变化可能式来自用户的输入,也可能式来自代码某处的setText,也就是说状态的变化可能不是一个源,这无形中增加了状态同步的工作量,比如EditText由于自己持有mText状态,所以其他组件需要监听他的状态变化,反之他也可能需要监听其他组件的状态变化,在Compose中使用的是单一数据源,这一点决定了Composeable数据流的单向流动,即数据总是自上而下流动,而事件总是自下而上传递,如图所示:

在这里插入图片描述

4.Compose 与View的关系

传统Android View的视图树如下图所示

在这里插入图片描述

Compose的视图树如下图

在这里插入图片描述

这两种树的节点类型不同,但是他们依然可以共存于一棵树中,就像DOM节点与AndroidView也不同,但是可以通过WebView显示在一棵树上,Compose也可以借助这样一个连接点挂载到View树上,而这个连接点就是ComposeView,ComposeView有一个唯一的子节点AndroidComposeView,它既是一个ViewGroup也是一个LayoutNode视图树的持有者,它实现了LayoutNode与View视图结构的连接,

CompsoeView继承自AbstractComposeView,AbstractComposeView有三个子类,分别对应Activity的窗口,Dialog窗口与PopWindow窗口,AbstractComposeView的子类负责Android平台的各类窗口的适配并生成对应的Composition,ComposeView作为一个子类负责Activity窗口适配。总结起来就是:ComposeView负责对Android平台的Activity窗口的适配,AndroidComposeView负责连接LayoutNode视图系统与View视图系统

注释:Composition是视图树的创建者,从Composable函数到视图树的生成经历的过程:第一步是Composeable函数执行后填充SlotTable,SlotTable中记录着Composable执行过程中的状态信息;第二步是基于SlotTable生成和更新LayoutNode视图树,Composition负责从Composable执行到视图树生成(更新)的整个过程

总结

本文主要是介绍了Jetpack Compose是什么以及他和传统Android view的区别,并且还介绍了Compose Api 的设计原则,Compose 只用Kotlin的DSL就完成了UI的编写,不用再去整XML,然后findViewByID了,想想就激动,而且现在的Android主要是用Kotlin开发,听说还要搞跨平台,字节也宣布后面的重点是Kotlin+Compose的方式,所以Compose 真的值得学。后面就进入实战的环节了,希望能和各位大佬一起交流学习Jetpack ComPose.