发表时间:2019.11.7android
在前不久的 Android Dev Summit '19 上,Jetpack Compose 终于发布了一个可直接得到的预览版。如今的版本仍是 0.1.0-dev02,处于很是早期的版本,官方也再三强调很是有可能产生变化且没法用于生产环境。不过我认为这是简单了解一下 Compose 的好时机。有备而无患。git
首先来了解一下如今尝试 Compose 所须要的环境:github
好的,这篇文章就到此为止吧。编程
等等!写都写了,我仍是再多写一点吧。网络
演这么一出其实也是为了说明,Compose 真的还处于很早期的阶段,估计还须要很长一段路才能真正在项目中实际使用上。但早鸟多少能尝到些甜头。但愿各位能经过简单的了解,预判一下之后的开发趋势,趁早规划,适时投资。数据结构
同时因为 Compose 还处于极可能发生不少变化的状态,因此本文也不许备过多拘泥于使用的细节,而是从更为大局的层面上介绍一下 Compose。固然,笔者本人经验和眼界极为有限,真知灼见是没有的,但愿起到抛砖引玉的做用。框架
请记得下载一个最新的 Android Studio,须要 4.0 版本,在发文时这意味着你须要使用 canary channel 版本的。编辑器
开始新建一个项目,会发现多了一个 Empty Compose Activity 的选项,选择它,各类依赖会为你配置好。那么一个 hello world 会是这个样子的:ide
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp()
}
}
}
@Composable
fun MyApp() {
Text("Hello world!")
}
复制代码
好的,你已经知道了 Compose 的基础知识,如今能够尝试用它来构建各类界面了。函数
请先慢着动手。若是去看官网的入门教程,你所获得的核心内容的确就是这样。因为文档及教程还很不完善,这里我建议,出门左转学习一下 Flutter。
这不是一句玩笑话。Compose 在控件的使用以及组合上,跟 Flutter 更为相近,而跟 Android 以前的那套 UI 没有太大的关系。使用 Layout Inspector 这个工具来查看 Compose 编写的应用,能够看到 Activity 内是一个 AndroidComposeView 包含了不少 RepaintBoundaryView。而没有使用原先就有的 TextView 等控件。
假如你只接触过 Android 的 UI 编程,可能须要一段时间来熟悉而后转变原先的思惟。虽然 Compose 自己还很不完善,但这种声明式的编程范式(declarative programming)能够经过学习 React 或者 Flutter 等 UI 框架未雨绸缪一番。
关于声明式编程稍后再提,我仍是继续谈一下一些常见的情形。
在布局上,首先会教会你使用 Column 和 Row,可以对应代替 LinearLayout;FrameLayout 也换成了 Stack。若是你对 main axis、cross axis 还比较陌生,如上所说,能够尝试学习一下 React 和 Flutter。
视频中提到,Compose 对 ConstraintLayout 的支持还正在进行中。因此能够猜想还在对于现有的布局控件,之后应该仍是会添加支持的。
大多数应用都逃不了网络请求 + 列表展现!
Compose 提供了 VerticalScroller 和 HorizontalScroller 来生成列表,在使用上与 RecyclerView 是彻底不一样的体验:
@Composable
fun MyApp() {
VerticalScroller {
Column {
repeat(20) {
Row(mainAxisSize = LayoutSize.Expand) {
Container(height = 48.dp) {
Text("Item $it", modifier = Spacing(left = 16.dp))
}
}
}
}
}
}
复制代码
事实上,Scroller 与 ScrollView 更接近,只提供了一个滚动的功能,并没提到有对 View 进行回收复用。
@Composable
fun Greeting(name: String) {
MaterialTheme {
Surface(color = Color.White) {
Text(text = "Hello $name!", style = +themeTextStyle { h5 })
}
}
}
复制代码
以上代码添加了 Material 的主题。
在我看来,这种方式比使用 XML 那套繁琐、不直观、缺少文档的方法要好太多。固然,也可能只是由于我菜。
Android Studio 4.0 还提供了一个名为 Live Preview 的功能来预览 Compose 的效果。经过给 Compose 函数添加 @Preview
注解来预览该函数的效果。这个函数必须是无参的,并且能够给注解传递不一样的参数来预览各类不一样状况下(不一样主题不一样屏幕大小等)的界面。
功能是好功能,但代码发生变更后,必需要从新 build 后才能更新预览,如今效率还比较低。
最后谈谈当状态(数据)发生变化后,Compose 如何响应。
@Model
class State(var count: Int = 0)
@Composable
fun MyApp() {
val state = State()
MaterialTheme {
Stack {
aligned(Alignment.Center) {
Button("${state.count} clicks", {
state.count++
})
}
}
}
}
复制代码
上面这段代码,放置了一个按钮,每按一次按钮上的计数就会 +1。代码里并无对 State 进行监听,而后再对 UI 进行更新。而是在 State 类上添加了 Model
注解,Compose 自动进行 UI 的更新(官方称之为 recompose)。
你或许会想:哦,setState()
。
Android 已经十年,设备的变化很是大,也涌现出不少心的开发技术和思想,但用来开发 UI 的工具却还依旧停留在十年前。很多控件已通过时并且背负了太多历史包袱,从新开始或许是更好的选择。
开发 UI 须要编写 XML 布局,经过代码加载,可能还须要经过 XML 来定义 style,为了编写一个界面要作的工做太多了。并且考虑到 Activity 和 Fragment,须要顾及的就更多了。若是要自定义一个 View,要作什么工做?我想“自定义 View”这几个字,都能吓退一批人吧。
而且大量 UI 工具与系统的版本绑定,新功能新修复没法及时让开发者和用户受益。Material design?Who cares?那是 5.0 以上才大部分支持的东西,更别提 shape theming 了。
原先的控件使用了一些只有官方能使用的黑魔法,也就是 hidden API。Compose 将彻底在公开的 API 上进行构建,官方使用的广大的普通开发者也可以使用。
插点私货。我偶尔会看着隔壁 Flutter 流下羡慕的泪水。它提供了大量官方的控件,应对各类场景,并且在各类系统版本上提供统一的行为。而我却须要满世界找非官方的实现,一个个查看是否知足个人需求,是否还在维护,是否须要本身魔改。固然,我无比感恩这些开发者的贡献,但我以为咱们应该被 Android 官方善待。
而后是 data flow。对于 UI 编程来讲,分发事件和接收状态是与开发者关联最密切的事情。而现有的 android.widget 在这两个方面都作得不够好:状态的管理比较混乱;事件在分发时就已经改变了控件的状态;listener 能够跟 Kotlin 结合更紧密提供更合适的作法。
声明式编程一般是相对于命令式编程(imperative programming)来讲的,不关注编程中具体的过程,而是以最后的结果为重点。在 UI 这一特定的领域来讲,声明式编程则意味着:当状态发生变化时,声明式框架会自动更新视图。
声明式的 UI 框架会关注:
也就是说,它只关心当前的数据(状态)会渲染出什么样的外观,而不把数据当成一个拥有上下文的状态流来看待。
Composition over inheritance.
组合优于继承。
Compose 经过组合的方式构成界面。这或许也是起名叫 Compose 的缘由。
遵循单一责任原则,Compose 函数都只有一个单一的目的,想实现某一种效果,就使用对应的 Compose 函数。好比想要设置背景,则须要使用 Surface
,没有其余 Compose 函数能够作到这一点。
使用 @Composable
注解的函数只能在另外一个的 Composable 函数中调用。看到这句话,你可能会想起:“ 只有替身才能打倒替身 !”
若是你对 Kotlin Coroutine 有所了解,suspend 函数也一样只能在 suspend 函数中进行调用。而 coroutine 的实现,是 Kotlin 编译器在编译时,将 suspend 函数进行了改造,会给函数添加一个 Continuation 参数,并对函数体进行必定程度的改造。详细的这里很少写了。
对于 Composable 函数,一样也是使用了 Kotlin 编译器插件将函数变形了。Composable 函数里添加的则是 Composer,这是一个相似于 gap buffer 的数据结构。Gap buffer 在文本编辑器里被广泛使用,有兴趣的能够多了解一下。
再次强调,Compose 处于很早期的阶段,API 也好,具体的底层实现也好,都极可能会发生变化。官方的示例 JetNews 也存在必定的性能问题。
因此我以为普通开发者还不须要去了解具体使用的细节。但仍是有几个建议:
Codelab - Jetpack Compose Basics
Declarative UI Patterns (Google I/O'19)