Jetpack Compose是什么?
它是一个声明式的UI工具包(declarative UI toolkit for AndroID).
它的主要目的就是改变之前命令式地(imperatively)写UI的方法, 改成声明式(declarative)的.
命令式AndroID之前的写法就叫命令式: vIEw hIErarchy是一个UI Widgets构成的tree, 当app的状态改变时, UI需要更新. 通常的做法是通过findVIEwByID()
等手段找到要更新的节点, 通过setText()
, addChild()
, setimageBitmap()
等方法更新控件的内部状态. 每个控件都有自己的内部状态, 并且暴露getter/setter, 允许程序逻辑和控件交互.
命令式为什么不好呢:
这样手动地更新vIEw会增加犯错的可能性. 如果某一数据在多个地方被渲染, 那么很可能就忘了更新其中的某个vIEw.很容易创建非法状态, 比如两个更新以不期望的方式冲突了. (比如: 一个要更新值, 另一个要移除节点.)维护的复杂度随着需要更新的vIEw个数而增加.声明式所以, 在过去的几年里, 业界一直在探索并且开始转向一种声明式的UI模型. 目的就是简化构建和更新UI.
Jetpack Compose是一个声明式的UI framework. 该技术的原理是从头开始重新生成整个屏幕, 然后仅应用必要的更改. 这种方法避免了手动更新stateful vIEw的复杂度.
在Compose的声明式解决方案里, Widgets相对来说是stateless的, 不暴露getter/setter.
实际上, Widgets根本不是以对象的形式来暴露的.
当更新UI的时候, 实际上是传不同的参数调用了composable方法. 当数据改变时, composable负责把当前的应用状态转化为UI.
Compose的优势:
目前Google投入了大量的资源(学习资源, 社区挑战赛, IDE和编译器支持, 推出desktop版本等)来推广Compose, 我们有理由相信Google官方会继续发力, Compose会成为AndroID未来的UI标准开发形式.Compose的声明式写法和Flutter, SwiftUI, React契合, 在支持多个平台的团队里, 有利于架构思想的统一.声明式UI, 写起来更快, 不容易出错.因为所有的代码都是Kotlin写的(真100%kotlin), 利用了Kotlin的强类型安全, 编译器会提示很多错误.修复和更新了一些旧的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相邻的这一层.
@H_502_93@4.技术的组成部分和关键点.Jetpack compose的总体特点:
声明式UI.f(state)=UI
.Built on Kotlin.Unbundled: 不是和系统绑定的, 而是和Jetpack中的库一样, 版本独立, 可以自己更新维护版本, 也保证了多个系统上的行为一致.Built for interop. 可以和已有VIEw互相调用, 适用于现有项目的逐渐迁移.内置控件和theming, 支持material design.Composable functionsCompose的使用方法:
定义一系列的composable functions: 接收数据, 发射UI元素.
@Composablefun Greeting(names: String) { Text("Hello $name")}
Composable方法的特点:
所有的方法都必须有@Composable
注解.方法参数是数据.通过调用其他composable方法来发射UI元素.方法不返回值, 因为它们在描述屏幕状态, 而不是构建UI Widgets.方法要快, 具有幂等性(调用多少次结果都一样), 没有副作用. (fast, IDempotent, and sIDe-effect free.) 这就要求方法不会修改外部属性或者全局变量, 也没有Random的调用等.还有一个小区别就是不同于普通的kotlin方法命名规范, composable方法名的首字母要大写, 因为它此时代表的是一种Widget.
RecompositionCompose framework会很机智地选出有变化, 需要重新绘制的部分.
在Compose中, 如果调用composable function, 传入了新数据, 会使得方法被recomposed: 这个方法发射的Widgets会根据需要进行重新绘制.
因为重新绘制整个UI tree会花销比较大, 所以实际上composable function只有input改变的才会被重新绘制, 对于那些参数没有变化的方法和lambda, 其实是skip掉的, 这样才能提高recompose的效率.
所以, 永远不要依赖于执行composable function的sIDe-effects, 因为recomposition有可能会被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的底层原理, 目前还没找到一个官方的文档或者架构图.
因为可能大家都还在学习怎么使用, 这项技术的底层实现细节还没有被热烈讨论起来.
这里有个问题: https://stackoverflow.com/questions/58558163/how-does-jetpack-compose-work-under-the-hood
从使用者的角度揣测一下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的混用粒度更细一点.都可以一边改UI一边预览.Jetpack Compose比Flutter好的地方:
基于Kotlin, 相比于Flutter的dart来说, 对AndroID开发者更友好一些.接着上一点, 因为Compose只改了UI, 所以其他部分的代码库仍然是AndroID原生代码的逻辑, 趁手的第三方库比较多. 而Flutter, 就得利用其它package来做Json解析, 数据库等等.Flutter的stateful Widget改状态必须要在setState里, 使用上不是很方便, 容易出错.Jetpack Compose的Recomposition看上去更智能一些, 完全自动, 不像Flutter一样需要开发者自己设置一些flag来表明哪个部分不需要重绘.安装包体积应该有优势? 因为Flutter SDK包含了自己的图像引擎, 而Compose是没有native层面的东西的.Flutter比Jetpack Compose好的地方:
Flutter还支持iOS.Flutter相比Jetpack Compose稍微成熟一些(Flutter出来的早一些), 是经过一些app的实际上线验证的.Flutter是有自己的图形引擎Skia的, 绘制会更有效率? (没有验证, 纯猜测)ReferenceThinking in ComposeUsing Jetpack librarIEs in Compose | Session -> 这个讲状态管理和其他Jetpack库结合的视频很棒. 总结以上是内存溢出为你收集整理的Jetpack Compose What and Why, 6个问题全部内容,希望文章能够帮你解决Jetpack Compose What and Why, 6个问题所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)