一个最简单的例子
安装最新版本的 Android Studio 后,打开AS,然后选择 New Project 来创建一个应用,然后在 手机和平板电脑类别,选择 Empty Activity.
在空活动中替换成如下代码
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.Text
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Text("Hello world!")
}
}
}
以上是一个最简单的Android例子,就显示一行文本到界面上面,叫“Hello world!” ,没有其他内容。代码也很简单,顶部四个import是引入必要的库,这些库都是Android sdk内置的。
然后有一个类,MainActivity ,这个类继承自ComponentActivity
这是Jetpack Compose 基础Activity,在屏幕上显示一行文字 Hello world!
1. import 导入包(引用系统类)
import android.os.BundleCode language: CSS (css)
Bundle:用于页面之间传递临时数据,onCreate 的参数,保存页面销毁前状态。
import androidx.activity.ComponentActivityCode language: CSS (css)
ComponentActivity:AndroidX 提供的基础Activity,Compose项目必须继承它,是页面载体。
import androidx.activity.compose.setContentCode language: CSS (css)
setContent():Compose 核心函数,用来把Compose UI挂载到Activity上,替代传统XML的 setContentView。
import androidx.compose.material3.TextCode language: CSS (css)
Text:Material3组件,用于展示文本,相当于XML里的TextView。
2. 定义主页面类
class MainActivity : ComponentActivity
MainActivity:应用入口页面(AndroidManifest里默认注册的启动Activity):代表继承,继承ComponentActivity
3. 生命周期 onCreate
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)Code language: JavaScript (javascript)
onCreate:Activity创建时第一个执行的生命周期方法,页面初始化写在这里override:重写父类方法super.onCreate(savedInstanceState):必须调用,执行父类的初始化逻辑,不写会崩溃savedInstanceState:Bundle类型,页面被系统回收重建时,用来恢复保存的数据
4. Compose UI入口 setContent
setContent {
Text("Hello world!")
}
Code language: JavaScript (javascript)
setContent {}:Compose的UI作用域,大括号内写所有Compose可组合项Text("Hello world!"):可组合函数,渲染文本到屏幕
最令人不解的应该是最后一个
setContent {
Text("Hello world!")
}Code language: JavaScript (javascript)
下面我们解析一下
setContent 是调用函数,而且是带【Lambda表达式(代码块)】参数的函数。
setContent { Text("Hello world!") }
Code language: JavaScript (javascript)
等价于:
setContent( /* 传入一个函数 */ )
Code language: JavaScript (javascript)
Kotlin 语法
Kotlin 有一条语法糖:
如果函数最后一个参数是函数类型,可以把这个lambda大括号写到圆括号外面; 如果只有这一个参数,圆括号甚至可以直接省略。
setContent 的函数签名简化版:
// 伪代码,setContent定义大概长这样
fun setContent(content: @Composable () -> Unit) {
// 内部负责承载Compose UI
}
Code language: JavaScript (javascript)
参数 content 的类型:不带参数、无返回值的 @Composable 函数
所以下面两种写法完全一模一样:
// 写法1:省略括号(代码里的写法,最常用)
setContent { Text("Hello world!") }
// 写法2:完整写圆括号,更容易看懂本质
setContent( { Text("Hello world!") } )
Code language: JavaScript (javascript)
所以setContent { Text(“Hello world!”) } 其实就是调用setContent 的函数进行界面的描述
androidx.activity.compose.setContent 这个函数就是定义在这里。所以我们前面引入了这个函数。
另外setContent { Text(“Hello world!”) } 就是传入一个函数体{ Text(“Hello world!”) }给这个函数。只不过省略了圆括号而已,因为kotlin规定,如果只有一个参数(就是这个lambda函数)的时候,是可以省略圆括号的。
里面的 Text("Hello world!") 又是什么?
Text() 也是函数!叫「可组合函数」,带 @Composable 注解
- 不是View对象,不是new实例
- 调用它不会立刻画UI,只是描述UI长什么样
- Compose运行时会反复执行这个lambda,来刷新界面(重组recomposition)
重点误区纠正: 不是“setContent执行完,立刻绘制Text”
setContent只是把这个lambda代码块交给Compose框架托管 之后框架会在合适时机(页面创建、状态变化)执行这个代码块,执行到
Text就生成对应的UI节点。
关于上面的lambda表达式函数的写法,补充,请看下面的kotlin的例子
注意:下面例子和android 没关系,是属于kotlin的语法
/**
* You can edit, run, and share this code.
* play.kotlinlang.org
*/
fun main() {
println("Hello, world!!!")
runAction {"hello"}
}
fun runAction(block: () -> String) {
val result = block() // 执行lambda
println(result)
}Code language: PHP (php)
本例子中, runAction {“hello”} 这里的{“hello”} 相当于一个函数体,传给了block函数,这个函数的函数体 就{“hello”}
也就是 block函数就等价于
fun block() {
"hello"
} Code language: JavaScript (javascript)
在kotlin中
fun block() {
“hello”
}
fun block() {
return "hello"
} Code language: JavaScript (javascript)
所以 runAction 函数里面 就相当于 调用block后 把里面的hello字符串赋值给result 这个变量,然后打印出来。

以上是最终执行结果。