1. 简介
开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
任何的新技术的出现都有其需要解决的问题,Compose
当然也不例外
Compose主要解决的问题就是原生Android的UI开发,随着近年大前端趋势的愈演愈烈,React的声明式UI也深入人心,推动了新一代UI的变革,Compose在设计方面对此也多有借鉴
1.1. 特点
从官方给出的文档来看,主要有以下几个特点:
- 更少的代码
- 直观
- 加速开发
- 功能强大
在后续的开发中将会逐渐体会到它所带来的好处
更少的代码
主要是现在提倡低代码开发,Compose在代码方面进行了改进,相对于传统的XML布局、View的继承和对应的命令式操作,Compose只需要开发者关注UI的描述,并且使用了更加简洁的语法用以描述UI
直观
相对于XML的布局形式,Compose增加了代码的可读性,直接用函数描述界面的结构
加速开发
Compose提倡使用组合,这一点也与React当中的组件思想有异曲同工之妙,可以增强代码的复用性,同时加速开发的效率
功能强大
Compose的代码能够与原来传统的布局兼容,并且兼容到API 21,对各常用三方库都兼容,稳定兼容正是强大的一方面
2. 命令式UI与声明式UI
如果之前有接触过React,可能对这二者的区别已经有所了解了
Android在显示界面方面的流程其实也和JS一样,显示找到对应的UI元素,然后进行相应的操作,比如设置属性,获取内容之类的,这便是命令式UI
在Android中,我们通过XML或者new
出View类型的对象生成UI布局之后,会调用findViewById()
等方法去找到布局里对应的元素,然后通过返回的对象执行操作
这种场景就像是找人办事,分为找、做两个步骤,看上去其实还好,但是当你需要找的人多了,问题就来了 —— 我要找100个人,每个人有不同的任务(写代码的毕竟是人,情况复杂了犯错的概率也就上升了),此时不仅代码量大大增加,出现问题的风险也增加了,同时还会有可读性的问题
而声明式UI相对更简单,只需要搭建好UI的描述,其他的数据处理交给专门的逻辑,如果打个比方的话,这就像是大型公司的架构,将公司的结构组织好,等到业务来的时候,从上层传递下去,由对应部门负责处理,相当于早已摆好了架势,一方面也是一种大局观的体现
3. 设计原则
3.1. 一切皆为函数
在Compose当中,组件是Composable函数,通过@Composable
注解,将函数作为组件,相互直接可以进行组合,并且Composable函数只能在Composable函数中被调用
并且,在Compose当中,不包含类的概念,因而所有组件都是Kotlin中所谓的顶层函数
3.2. 组合优于继承
继承带来方便的同时,也引起了一系列问题,比如说代码功能的冗余,可读性变差等
在Android中有各种各样的View
,它们都直接或间接继承了View
,这也就导致有些东西也许用不到,但还是硬生生地继承过来了
Compose是希望通过使用组件进行组合,像搭积木一样,把需要的组合到一起,拼出想要的,一方面能够复用,另一方面也是减少了无用的部分
3.3. 单一数据源
单一数据源的原则是声明式UI的重要原则
简单来讲就是组件UI的变化需要归纳为一个原因,这样才能确保UI状态的可控,否则会有更多的同步开销以及产生数据问题的风险
在UI交互方面,数据总是保持自上而下的流动,而事件则是自下而上的传递
4. 环境搭建
主要就是需要版本比较新的Android Studio,现在Android官网上能够下载到的已经是可以支持的了,官网上还附带有Compose开发的样例图片
点击下载Android Studio,安装步骤对应的说明在当前页面的下方也可以找到,“Install Android Studio”就是对应的安装说明,点击跳转便可以查看,里面也有对应的指导视频,过程这里就不赘述了
5. 第一个Compose应用
5.1. 创建
直接打开Android Studio,从头开始创建一个Compose项目
新建项目的时候,从提供的项目模板中选择“Empty Compose Activity”,这便是Compose项目的模版,然后选择“Next”下一步
接着简单填写一下项目的信息,“Finish”完成项目的创建
等待项目创建完成后,可以看到,Android Studio为我们创建了一些模板代码,默认生成一个MainActivity,继承自ComponentActivity
,右侧是预览页面
其他先不做,现在先直接运行一下
这便是Compose应用的一个HelloWorld Demo,正如各个技术入门的传统一般,接下来对其中的代码进行分析
5.2. 分析
学习要知其然,知其所以然,在学习运用后需要进一步深入分析原理,才能力求精进
先前只是对已有的程序进行简单的执行,下面对于代码的逻辑进行简要的分析,了解为何能够在屏幕上呈现“Hello Android!”的结果
正如刚刚所看到的,代码主要集中在Android Studio为我们创建的MainActivity.kt当中,除去顶部的包名以及包导入,其他内容如下所示:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposeDemoTheme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
Greeting("Android")
}
}
}
}
}
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
ComposeDemoTheme {
Greeting("Android")
}
}
Composable组件
onCreate()
是Activity的生命周期回调,除此以外,下面有两个方法,它们都带有@Composable
注解,这两个方法就是Composable组件,代表两个UI控件
我们的项目中并没有加载XML布局文件,setContent{}
正是通过这种名为Composable组件的方法加载的布局
Greeting()这个方法能够传入参数,name便是传入的参数,然后内部调用了Text()
方法,将字符串拼接后的结果再传给Text()
,其实Text()
也是一个Composable组件,如同原本的TextView
一样,用于显示文本字符串,因此Greeting简单封装了一层,或者说是组合了文本控件的功能,使其根据传进来的name参数显示文本,Greeting("Android")
自然就输出了“Hello, Android!”
另外,Composable组件都是顶层函数,也就是单独声明在Kotlin文件的最外层的函数,这样可以任意进行调用,并且Composable函数只能被Composable函数调用,这就形成了树形的调用结构,在这里扮演树根的就是setContent{}
块,setContent{}
接受Composable组件作为内容
组件预览
涉及UI界面的开发埋着头盲写可不行,需要随时预览开发的效果才能更加高效精准
在DefaultPreview()这个Compose组件上还有一个@Preview
注解,这便是用来预览组件的
在Composable组件有参数同时又没有给默认值的情况下是没有办法进行预览的
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
ComposeDemoTheme {
Greeting("Android")
}
}
给Composable加上@Preview
注解后,打开右侧的预览面板便可以预览对应的组件了
对于页面的修改后需要编译,重新刷新预览,确保显示正确
如果有多个@Preview
标注的Composable组件,可以同时预览,更换@Preview
的参数在UI适配的时候会更加有效率
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
ComposeDemoTheme {
Greeting("Android")
}
}
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun DefaultPreviewNight() {
ComposeDemoTheme {
Greeting("Android")
}
}