HelloWorld例子

一个最简单的例子

安装最新版本的 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 这个变量,然后打印出来。

以上是最终执行结果。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注