- 修复和更新了一些旧的API: (Buggy Android Views: Picker, Spinner, EditText, 有一些edge cases. 因为要更改旧的总是很难, 不如创建一个新的. )
- 基于组合的Composable, 比基于继承的View体系, 更加灵活, 易于复用. 比如可以通过组合来达到复用多个源, 不再受单继承限制.
以Button为例, 在传统的UI里, 它是单继承体系下的一个类: Button -> TextView -> View. 而在Compose的世界里, 它只是一个@Composable
的方法, 里面包含了其他composable, surface, row等. 举例: list->detail两个界面, 可以通过提取方法参数来达到两个界面的composable复用.
- 支持和View-based UI系统的互相调用. 这样有两个优点: 有利于已有项目app的混用和逐步迁移; 当Compose满足不了需求的时候可以用传统View作为第二选择.
- 和Jetpack系列的其他库都能完美结合. (ViewModel, Kotlin Flow, Coroutines, Paging, Hilt, Navigation…)
劣势:
- 需要用Canary版本的Android Studio, 目前(2021.5)IDE还是存在一些问题的.
- Gradle也要升级到最新版(7.0.0-alpha15), 不是很稳定, 还有一些问题.
- 版本更新频繁. Compose alpha版本的一些API已经变了. -> 但是目前已经beta, 最新的Google I/0说7月就会有稳定版发布.
- 相比Android View, 社区支持不够多. -> 但是Google已经投入了大量的资源来推广, 社区支持正在飞速增长.
- 虽然Google封装了material的compose库, 但还是有一部分View控件没有办法提供, 比如WebView, MapView等.
3.这个技术使用的场景.
Jetpack Compose的使用场景是取代原来的Android View写法(xml, 在代码里实例化View对象再添加到View hierarchy里等), Jetpack Compose用全新的方式来写UI, 即将成为Google Android标准写法.
注意这里的改变除了UI写法的改变, 还是一种状态管理思想的转变. 声明式, 单向数据流, 单个数据源. Android内部的模式近年来一直追求的无外乎就是数据和View的分离, View的无知与自动更新, 清晰的逻辑管理和分离, 可测试性等等.
除了与View强相关的这一层(ViewModel)外, 其他的业务逻辑, 数据交互等被影响不大, 所以即便app决定逐渐迁移到Compose, 也只用管View绘制以及和View相邻的这一层.
4.技术的组成部分和关键点.
Jetpack compose的总体特点:
- 声明式UI.
f(state)=UI
. - Built on Kotlin.
- Unbundled: 不是和系统绑定的, 而是和Jetpack中的库一样, 版本独立, 可以自己更新维护版本, 也保证了多个系统上的行为一致.
- Built for interop. 可以和已有View互相调用, 适用于现有项目的逐渐迁移.
- 内置控件和theming, 支持material design.
Composable functions
Compose的使用方法: 定义一系列的composable functions: 接收数据, 发射UI元素.
@Composable
fun Greeting(names: String) {
Text(“Hello $name”)
}
Composable方法的特点:
- 所有的方法都必须有
@Composable
注解. - 方法参数是数据.
- 通过调用其他composable方法来发射UI元素.
- 方法不返回值, 因为它们在描述屏幕状态, 而不是构建UI widgets.
- 方法要快, 具有幂等性(调用多少次结果都一样), 没有副作用. (fast, idempotent, and side-effect free.) 这就要求方法不会修改外部属性或者全局变量, 也没有Random的调用等.
还有一个小区别就是不同于普通的kotlin方法命名规范, composable方法名的首字母要大写, 因为它此时代表的是一种widget.
Recomposition
Compose framework会很机智地选出有变化, 需要重新绘制的部分.
在Compose中, 如果调用composable function, 传入了新数据, 会使得方法被recomposed: 这个方法发射的widgets会根据需要进行重新绘制.
因为重新绘制整个UI tree会花销比较大, 所以实际上composable function只有input改变的才会被重新绘制, 对于那些参数没有变化的方法和lambda, 其实是skip掉的, 这样才能提高recompose的效率.
所以, 永远不要依赖于执行composable function的side-effects, 因为recomposit
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
ion有可能会被skip掉.
side-effects包括:
- 更新共享对象.
- 更新ViewModel中的observable.
- 更新shared preferences.
由于composable functions有可能会被逐帧执行(比如动画期间), 所以它应该足够的快, 如果需要耗时的操作, 可以考虑后台的coroutine.
5.技术的底层原理和关键实现.
Compose的几个特点:
- Composable functions可以以任何顺序执行.
- Composable functions可以并行执行.
- Recomposition会尽可能地skip多的composable functions. 如果真的需要side-effects, 考虑用callback.
- Recomposition是乐观的, 它认为在本次重绘期间不会有新的状态改变, 如果有新的状态改变, 它可能会取消当前绘制, 以新的参数重新开始绘制.
- Composable function有可能会被执行得很频繁(比如动画), 所以避免耗时操作.
关于Compose的底层原理, 目前还没找到一个官方的文档或者架构图. 因为可能大家都还在学习怎么使用, 这项技术的底层实现细节还没有被热烈讨论起来. 这里有个问题: *.com/questions/5…
从使用者的角度揣测一下Compose的原理: 虽然Composable使用了注解@Composable
, 但是却没有添加注解处理器(kapt), 所以并不是依靠注解在编译期生成代码.
在添加依赖的时候需要在build.gradle
里添加:
composeOptions {
kotlinCompilerExtensionVersion compose_version
}
所以它和kotlin的编译器有关系.
这个视频: Understanding Compose (Android Dev Summit '19)在17:18开始讲实现原理.
@Composable
更像是一个语言的关键字. 可以类比suspend
, 有以下几个共同点:
- 改变了方法的类型.
- 强制了方法的调用上下文.
部分更新
用了定制化的Kotlin编译器插件, 数据改变时, 受数据影响的composable的方法会被重新调用.
6.已有的实现和它之间的对比.
Android View和Jetpack Compose的对比.
Android View和Jetpack Compose的相似点:
- 都是Android UI的写法.
Jetpack Compose改进了View系统的哪些地方:
- 不再需要担心深层嵌套. Compose UI不允许多遍的测量(multi-pass measurement), 改善了效率.
Flutter和Jetpack Compose的对比.
Jetpack Compose和Flutter的相似点:
- 声明式UI,
UI = f(state)
. - 都有web和desktop版本.
- 官方都提供了一些material的控件和资源, 比如都有个Scaffold, 提供脚手架.
- 都可以和原生混用, 虽然程度不一样, Compose的混用粒度更细一点.