【Android】【Compose】Compose知识点复习(一)

前言

最近有新项目,要用到Compose开发,发现以前学的Compose也忘了很多了,看来好记性还是不如烂笔头,记录一下Compose相关的知识点,以后再忘了也能翻一翻看看。

一、Modifier 与独立参数:核心功能 vs 外在表现
核心结论

独立参数决定控件「能干嘛、承载什么数据」(核心本质),Modifier 只决定控件「长什么样、放在哪」(外在表现),二者无法互相替代。

详细讲解

把控件比作 "外卖员" 就能快速理解:

独立参数

外卖员的核心职责:比如要配送的餐品(对应TextField的value)、配送地址(对应Button的onClick)------ 没有这些,外卖员就失去了存在的意义;

Modifier

外卖员的外在形象:比如制服颜色(对应background)、身高体型(对应size)、配送路线偏移(对应padding)------ 这些变了,核心配送职责不会变。

开发场景举例

用Modifier.clickable替代Button的onClick:Button的onClick是核心参数,自带「点击按压态、禁用态视觉变灰、无障碍支持」等原生特性;而给Box加Modifier.clickable,虽然能实现 "点击触发逻辑",但没有任何Button的原生交互反馈(比如禁用后还是原来的样式),相当于 "普通人穿了外卖服,却不会送外卖"。

TextField的value/onValueChange:这两个参数是TextField的 "灵魂"------ 没有它们,TextField只是个空盒子,根本不算 "输入框";而Modifier只能给它加圆角、调宽度,永远替代不了 "输入文本并响应变化" 的核心功能。

kotlin 复制代码
@Composable
fun DemoParamVsModifier() {
    // 1. 有核心参数的Button:自带禁用态视觉反馈
    Button(onClick = {}, enabled = false) { Text("禁用按钮") }
    
    // 2. 仅加Modifier.clickable的Box:无禁用视觉反馈
    Box(modifier = Modifier.clickable(enabled = false) {}) { Text("假按钮") }
    
    // 3. TextField核心参数不可替代
    var text by remember { mutableStateOf("") }
    TextField(
        value = text, // 核心数据(必传)
        onValueChange = { text = it }, // 核心逻辑(必传)
        modifier = Modifier.padding(10.dp) // 仅调整边距(外在)
    )
}
二、Modifier 重复执行规则:指令链而非 "覆盖式配置"

核心结论

Modifier 不是 "键值对"(比如size=100dp被size=200dp覆盖),而是「按顺序执行的指令链」------ 布局类 Modifier 叠加生效,绘制类 Modifier 层叠覆盖。

详细讲解

把 Modifier 链比作 "给蛋糕做装饰的步骤":

布局类 Modifier(padding/size)

padding:先给蛋糕围 1cm 奶油边(padding(10.dp)),再围 2cm 巧克力边(padding(20.dp)),最终边宽是 3cm(叠加);

size:普通size是 "建议尺寸"(先建议做 10cm 蛋糕,后建议做 20cm,最终按 20cm 做);requiredSize是 "强制尺寸"(比如强制做 8cm,不管之前建议多少,都按 8cm 来)。

绘制类 Modifier(background/border):先给蛋糕涂红色奶油(background(Color.Red)),再涂蓝色奶油(background(Color.Blue)),最终看到的是蓝色 ------ 因为绘制是 "顶层覆盖底层"。

开发场景举例

做商品卡片时,用两层padding实现 "外间距 + 内间距":

第一层padding(10.dp):让卡片和其他元素隔开(外间距);

第二层padding(5.dp):让卡片内容和边框隔开(内间距);

最终卡片内容整体内缩 15dp,这是 "叠加" 的核心价值,若用 "覆盖" 逻辑根本实现不了。

java 复制代码
@Composable
fun DemoModifierOrder() {
    // 1. padding叠加:最终布局尺寸=100+10+20=130dp
    Box(modifier = Modifier.size(100.dp).padding(10.dp).padding(20.dp).background(Color.Red))
    
    // 2. background覆盖:最终显示蓝色(后写的在顶层)
    Box(modifier = Modifier.size(50.dp).background(Color.Red).background(Color.Blue))
    
    // 3. requiredSize强制覆盖:最终尺寸80dp,忽略前序200dp
    Box(modifier = Modifier.size(200.dp).requiredSize(80.dp).background(Color.Green))
}
三、自定义 Compose 组件:参数设计的核心规则

核心结论

自定义组件参数遵循「核心参数→非核心参数→Modifier」的顺序:核心参数强制传(无默认值),非核心参数设默认值,Modifier 放最后且默认值为Modifier。

详细讲解

自定义组件就像 "定制奶茶"

核心参数:奶茶品类(比如珍珠奶茶)、甜度(正常糖)------ 没有这些,商家不知道做什么奶茶,必须强制选;

非核心参数:加冰 / 去冰、加小料(默认不加)------ 可选,不选就按默认来;

Modifier:杯子大小(大杯 / 小杯)、包装(袋装 / 杯装)------ 最后选,不影响奶茶本身的口味(核心)。

关键注意点

必须把外部传入的Modifier传给组件根布局:比如自定义按钮的根布局是Button,要写modifier = 外部modifier + 内部样式(如modifier.height(48.dp)),否则外部传的Modifier会失效;

绝对不能把核心数据塞进 Modifier:比如用Modifier.productData(product)传递商品信息,既语义混乱(分不清是样式还是数据),又会导致 Modifier 频繁重建,性能变差。

java 复制代码
// 自定义圆角按钮:参数设计规范
@Composable
fun RoundedButton(
    // 1. 核心参数:强制传,放前面(无默认值)
    text: String,
    onClick: () -> Unit,
    // 2. 非核心参数:设默认值,放中间
    buttonColor: Color = Color.Blue,
    // 3. Modifier:放最后,默认值为Modifier
    modifier: Modifier = Modifier
) {
    Button(
        onClick = onClick,
        // 组合外部Modifier + 内部核心样式(关键)
        modifier = modifier.height(48.dp).clip(RoundedCornerShape(16.dp)),
        colors = ButtonDefaults.buttonColors(containerColor = buttonColor)
    ) { Text(text) }
}

// 调用示例:核心参数必传,其他可选
@Composable
fun DemoCustomComponent() {
    // 基础调用:仅传核心参数
    RoundedButton(text = "基础按钮", onClick = {})
    
    // 自定义调用:覆盖非核心参数+追加Modifier
    RoundedButton(
        text = "绿色按钮",
        onClick = {},
        buttonColor = Color.Green,
        modifier = Modifier.size(200.dp) // 覆盖内部height(48.dp)
    )
}
四、Compose 函数的本质:不只是加 @Composable 注解

核心结论

真 Compose 函数 = @Composable注解 + 返回值 Unit + 描述 UI + 支持响应式重组;仅加注解的是 "伪 Compose 函数",无实际 UI 意义。

详细讲解

把 Compose 函数比作 "动态画板"

@Composable注解 = 拿到画板的使用权限(必要但不够);

返回值 Unit = 不是画完把画板拿走,而是在画板上 "描述要画什么"(不能返回 "画好的按钮 / 文本");

描述 UI = 在画板上画按钮、文本(核心价值,没有这个就是 "空画板");

响应式重组 = 画板能自动更新 ------ 比如画的计数从 0 变 1,不用重新画整个画板,只更新数字部分(靠mutableStateOf实现)。

开发场景举例

伪 Compose 函数:加了@Composable,但只做1+1的计算,不画任何 UI;或画了 UI 但用普通变量val count=0,点击按钮数字永远不变(无重组能力);

真 Compose 函数:加注解、画文本 + 按钮,用remember { mutableStateOf(0) }定义计数,点击按钮数字自动更新(重组)。

java 复制代码
// 1. 真Compose函数:支持响应式重组
@Composable
fun RealComposeFunc() {
    var count by remember { mutableStateOf(0) } // 可观察状态
    Column {
        Text("计数:$count")
        Button(onClick = { count++ }) { Text("加1") } // 点击更新状态,UI自动变
    }
}

// 2. 伪Compose函数:无重组能力
@Composable
fun FakeComposeFunc() {
    val count = 0 // 普通变量(非可观察状态)
    Column {
        Text("计数:$count") // 永远显示0
        Button(onClick = {}) { Text("加1") } // 点击无效果
    }
}
相关推荐
哆啦A梦15882 小时前
【vue实战】商城后台管理系统 01 项目介绍
前端·javascript·vue.js
fatiaozhang95272 小时前
九联UNP-SJA8-国科GK6323V100C-2+8G-安卓9.0-原厂强刷固件包-可救砖及开ADB教程
android·adb·电视盒子·刷机固件·机顶盒刷机·机顶盒刷机固件·九联unp-sja8
似霰2 小时前
传统 Hal 开发笔记4----实现 Hal 模块
android·hal
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ2 小时前
java实现登录:多点登录互踢,30分钟无操作超时
java·前端
一字白首3 小时前
Vue Router 进阶,声明式 / 编程式导航 + 重定向 + 404 + 路由模式
前端·javascript·vue.js
Android出海3 小时前
Google Play正式出手整治后台耗电应用
android·新媒体运营·产品运营·流量运营·用户运营
广州华水科技3 小时前
单北斗变形监测在水库安全中的应用与维护该如何实施?
前端
Winter_Sun灬3 小时前
CentOS7 交叉编译 ACE+TAO-6.5.13 安卓 arm64-v8a 静态库
android·ace