本文章首发于公众号 Android丨Kotlin,欢迎关注!编程
Hello 你们好,我是 wanbo,久等了,今天咱们来聊聊 Jetpack Compose。markdown
在 Beta 版发布以后,我先去阅读了官方的文档,而后在 Youtube 上面官方发布的 Jetpack Compose 的相关视频也所有看了一遍,以后又去参加了官方组织的 #AndroidDevChalleng 作了实际的上手体验。架构
今年主要是围绕 Jetpack Compose ,一共是四周的挑战内容,每周会有一个不同的题目,目的是让你从不一样维度熟悉 Jetpack Compose,如今已经进展到了第二周,有兴趣的朋友能够去关注一下。app
我如今对 Jetpack Compose 的理解也比较有限,还不是很深刻,可是在读完官方的文档以后,我以为 Jetpack Compose 有不少在设计上让我感到很惊艳的地方,因此就火烧眉毛的想和你们分享一下。ide
你能够对它保持关注,官方有任何学习内容看一眼就好了,有个大概印象写个 Demo 玩玩就能够了,千万别激进的在正式项目里使用它。函数
我以前写过两个 iOS 的独立项目,在最开始我都是用的 SwiftUI 去写的,写的时候很爽,毕竟是新东西,好奇心以及成就感是很是强的,但无一例外,我以后都用传统的命令式 UI 把它们重写了。学习
由于坑实在是太多了,大部分时间我都在解 Bug ,并且不少时候我都不知道是它自己的 bug 仍是我写出的 bug,固然这也和 iOS 自己闭源的缘由有关。优化
在 Jetpack Compose 开发本身的新 feature 以前,它首要的任务,是把现有的 View 组件所有翻译一遍,翻译也是有一个过程的,首先会把 View 表层的东西翻译完,好比如何写一个 TextView,如何写一个 Layout,如何写一个列表,在以后是翻译 View 里层的东西,好比 View 的各类 Listener,各类 Event。ui
我认为可能要到 Release 2.0 的时候,里层的大多数功能,才会支持完善,看不到的功能缺失,会出现不少不可预估的问题,而后你上网去搜如何解决 XXX 问题,发现你们都和你同样懵逼,不知道怎么办,由于这自己就是它的 bug,只有官方去修复和支持才能完全解决。lua
还有一个须要注意的点,就是生态,在生态不丰富以前,你只能选择官方支持的一些解决方案,遇到须要特殊自定义的功能,可能会增长你好几倍的开发成本。
因此,想要在正式项目里使用,必定要谨慎。
差别主要在两方面:UI 的构建和 UI 的刷新。
在维基百科中,命令式编程的定义是这样的:经过使用改变程序状态的语句,来实现某些功能和效果。声明式编程的定义是:在不描述其控制流程的状况下表达了计算的逻辑。
用白话来说就是
命令式编程须要告诉系统每一步要作什么,具体该怎么作,经过这样的一种流程实现咱们想要的功能。
声明式编程则是隐藏了怎么作这个流程,你只须要操做一些基本元素,经过组合方式,把你想要的效果搭建出来就行了。
使用声明式 UI 编写界面能够极大的减小代码量,同时也提升了容错率,整个 UI 构建逻辑也变得更加清晰、易读。
另外一个差别点在于 UI 的刷新层面
传统的 View 体系中,是经过调用 View 的某些 set 方法来更新 UI 的状态,这是一个手动更新 UI 的过程,这个过程的维护性一般会随着 UI 复杂度的增长而增长,很是容易出错。
在 Compose 里动态的 UI 是和数据绑定的,当数据发生变化的时候,能够自动更新 UI 的状态,彻底不须要手动更新,即便 UI 很复杂,咱们也只须要专一于数据的更新逻辑就能够了。
从 UI 的构建到 UI 的刷新,其实都是一个由复杂变简单的过程,让开发者能够更专一于业务逻辑的开发。
咱们仍是从 UI 的构建和刷新这两个层面来聊,但这一部分要引入两个新名词:组合和重组。
在 Compose 中,View 再也不是某个对象,是以 @Composable 标记的方法存在。
UI 的构建是经过组合不一样的 @Composable 元素实现,例如咱们要实现一个文本列表,能够选择 Column 元素(纵向列表),而后在内部声明 Text 元素,就能够很是快的实现。全部的 UI 效果均可以经过 Compose 中内置的基本元素组合实现。
@Composable 元素是互相独立的,不存在继承关系,这和传统的命令式编程是彻底不同的,元素的差别性也是经过组合实现的,经过组合不一样的内置基本元素来实现一个新的元素结构。
Compose 有一个很是核心的类 Modifier,能够理解为元素加强或元素修饰,每个 @Composable 元素均可以接受一个 Modifier,经过定义不一样的 Modifier 来修改元素的实际表现形式。
推荐你们经过元素组合的方式实现一个新的自定义元素,而后传入不一样的 Modifier 而达到自定义 View 的复用效果。
在 Compose 中,UI 的刷新是经过从新渲染生成整个屏幕实现的,这是全部声明式 UI 刷新页面的工做原理。
可是 Compose 会根据数据的变化,仅针对须要改变的元素作必要的修改,经过改变数据而从新生成组合 UI 这一过程称为重组。当数据更新了,虽然是从整个屏幕开始从新渲染,但与数据修改无关的元素,会保持以前生成的实例,由于 @Composable 方法渲染是很是快的、幂等且无反作用。
很是重要的一点就是幂等,幂等的意思是指可使用相同参数重复执行,并能得到相同结果的函数。这些函数不会影响系统状态,也不用担忧重复执行会对系统形成改变。说白了就是与数据修改无关的 @Composable 元素在屏幕从新渲染的过程当中不会被重组。
整个重组的过程是很是智能的,Compose 编译器会在 @Composable 元素初始化的时候,对每个元素作标记,而后根据数据是否修改来智能的选择须要被重组的元素。
咱们也能够增长额外的辅助信息,帮助 Compose 编译器作更精准的判断,一个典型的例子就是在动态列表中,若是咱们在最后添加一条数据,那么编译器就是认为前面的数据是没有任何修改的,仅重组最后一条元素。
可是当咱们在 index == 0 的位置,插入一条数据,那么编译器会认为整个列表都被修改了,由于在它的默认标记中会记录位置信息,在 0 的位置插入数据,意味着整个列表都须要被重组。
这个时候,咱们能够给列表的内容增长 key 的标记,一般是惟一不变的 id,告诉编译器还须要判断 id 是否变化,此时编译器仅会重组第一条元素,以后的元素依旧使用以前生成好的实例。
在 Compose 中 UI 刷新的惟一方法就是重组,是否重组的判断条件就是与 @Composable 元素绑定的数据是否发生了变化。
重组须要注意的地方
重组意味着系统会从新调用 @Composable 元素方法的执行,而重组可能会随时且很是频繁的发生,全部的 @Composable 方法的执行都是乱序和并行的,这一点咱们须要注意的。
因此到 @Composable 方法里面,任何一个 Local 变量,任何一个动态计算方法,任何一个更新数据的逻辑,都须要仔细考虑,否则就会出现不可预估的错误。
可能在重组过程当中,Local 变量会失效,动态计算方法会调用不少次,这里实际上是一个大坑,但愿 Android Studio 之后能够在 @Composable 方法里有严格的代码检查,帮助你们在写的时候就能够检查出一些潜在的错误。
一种相似于单项数据流的处理方式
动态的 @Composable 元素由上层传递的数据所控制,交互事件经过 Block 的方式再传回上层,经过在上层更新数据,从而实现 UI 的动态更新。数据传递是自上而下的,交互事件的传递是自下而上的。
按照这种逻辑,咱们须要在 ViewModel 中定义可变的数据,同时定义好修改数据的方法,把数据自上而下传递到实际的 UI 中,而后将 UI 的交互事件向上传递,经过执行最上层 ViewModel 中修改数据的方法,更新数据。
但这样其实会引起一个新的问题,当咱们的 UI 特别复杂的时候, @Composable 方法的参数可能会变得很是多。
这时候就须要你去使用不一样的内置基本元素来实现一个新的元素结构,经过组合的方式,优化代码的结构,相似这样。
虽然一眼看上去 Jetpack Compose 是一个全新的东西,但认真阅读了文档以后,其实都很好理解,重点是 Compose 加速了整个 Android 开发的速度,由复杂变简单,让咱们能够专一于业务逻辑上的实现。
包括这几年 Jetpack 的快速迭代,目的也是同样的,并且 Compose 和以前 Jetpack 中的那一套架构设计规则是能够无缝使用的,只是把咱们以前写 UI 的逻辑改变了。
Jetpack Compose 确定不是 Android UI 开发的最终形态,但绝对是 Android 技术生态上的一个巨大的进步。
固然仍是那句话,想要在正式项目里使用,必定要谨慎,再等等。
今天的分享就到这里,Compose 内容其实不少,一篇文章确实也没法彻底涵盖到,你们有其余关心的点,能够继续在评论区留言,下期我专门写一篇答疑文章~
欢迎关注公众号 Android丨Kotlin!