【Jetpack Compose基础语法学与练】第7课 if条件渲染 + 列表基础(LazyColumn)

前言

上一课学习了 TextField 文本输入,掌握字符串状态、 value 与 onValueChange 的单向数据流。

本课学习两大常用能力:if条件渲染(根据状态决定组件是否显示)、LazyColumn懒加载列表(长列表只渲染屏幕可见项,性能高效)。

前置:完成1~6课,掌握状态、可组合函数、基础布局

一、完整可运行示例源码

kotlin 复制代码
  
package com.example.composefirst

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ListDemoPage()
        }
    }
}

@Composable
fun ListDemoPage() {
    // 输入文本状态
    var inputText by remember { mutableStateOf("") }
    // 待办列表,字符串集合
    var todoList by remember { mutableStateOf(mutableListOf<String>()) }

    Column(modifier = Modifier.padding(20.dp)) {
        TextField(
            value = inputText,
            onValueChange = { inputText = it },
            label = { Text("输入待办事项") }
        )
        Spacer(modifier = Modifier.height(12.dp))

        Button(onClick = {
            if(inputText.isNotBlank()){
                todoList.add(inputText)
                inputText = ""
            }
        }) {
            Text("添加待办")
        }
        Spacer(modifier = Modifier.height(16.dp))

        // if条件渲染:列表为空时显示提示文字
        if(todoList.isEmpty()){
            Text("暂无待办,请添加任务")
        }else{
            // LazyColumn 懒加载列表
            LazyColumn {
                items(todoList){ item ->
                    Text(text = "· $item", modifier = Modifier.padding(vertical = 4.dp))
                }
            }
        }
    }
}

@Preview
@Composable
fun ListPreview() {
    ListDemoPage()
}
 

二、逐行代码解读

  1. if条件渲染
kotlin 复制代码
  
if(todoList.isEmpty()){
    Text("暂无待办,请添加任务")
}else{
    LazyColumn { ... }
}
 

Compose可组合函数内部可以直接使用Kotlin的 if 判断。

  • 条件成立:渲染if分支内的组件;
  • 条件不成立:渲染else分支组件;

原理:状态变化触发重组,重新执行函数,根据条件动态选择渲染哪一段UI。

注意: if 必须返回同类型的组件树,不能返回不同类型。

  1. LazyColumn 懒加载纵向列表
    Column 会一次性渲染全部子项,数据量大时卡顿。
    LazyColumn 是懒加载容器:只渲染当前屏幕可见的条目,滑出屏幕的条目会被回收,适合长列表。
  • items(集合) :批量遍历集合,为集合中每一项生成UI。
  • 对比: Column 一次性加载全部; LazyColumn 按需加载。
  1. 待办列表状态
kotlin 复制代码
  
var todoList by remember { mutableStateOf(mutableListOf<String>()) }
 

mutableListOf 可变集合,但是注意:修改集合内部元素,不会触发重组。

本示例 todoList.add() 可以刷新界面,是因为mutableStateOf会监听这个list引用变化;

易错点:如果只是修改list内部元素,引用不变,Compose不会感知,推荐使用 mutableStateListOf 专门做列表状态。

  1. 添加按钮逻辑
    点击按钮,判断输入不为空,添加到列表,清空输入框;状态变更触发重组,列表自动刷新。

三、补充知识点:mutableStateListOf(推荐列表状态)

上面示例的优化写法,专门的可观察列表,修改内部元素也能触发重组:

kotlin 复制代码
  
var todoList = remember { mutableStateListOf<String>() }

直接调用 todoList.add() 、 todoList.remove() ,自动通知Compose刷新界面,开发列表优先使用这个。

四、综合练习题

填空题

  1. Compose中实现根据状态动态展示UI,可直接使用Kotlin的________语句。
  2. 适合大量数据、按需渲染的纵向列表组件是________。
  3. LazyColumn遍历集合生成列表项,使用________函数。

答案与解析

  1. if ;解析:Compose是函数式UI,直接在代码内用if做条件渲染。
  2. LazyColumn ;解析:懒加载列表,只渲染屏幕可见条目,适合长数据。
  3. items ;解析:LazyColumn内部DSL,遍历集合生成每一行UI。

判断题

  1. Column适合上万条数据列表,性能和LazyColumn一样。()

答案:错误。理由:Column一次性渲染所有子元素,大量数据会造成页面卡顿;LazyColumn懒加载回收视图。

  1. if条件渲染,条件改变后,Compose会触发重组自动切换UI。()

答案:正确。理由:状态变更触发重组,重新执行可组合函数,if判断重新执行,切换界面。

  1. mutableStateListOf 列表,调用add添加元素,会自动触发界面重组刷新。()

答案:正确。理由:mutableStateListOf是Compose专用可观察列表,增删元素会通知框架刷新UI。

简答题

  1. 简述 Column 和 LazyColumn 的核心区别,各自适用场景?

参考答案:

Column一次性渲染全部子组件,适合少量固定布局内容;

LazyColumn懒加载,仅渲染屏幕可见条目,条目滑出屏幕回收,适合数量不确定、大量数据的滚动列表。

代码实操题

修改代码:给每一个待办项增加删除按钮,点击删除对应条目。参考答案

kotlin 复制代码
  
@Composable
fun ListDemoPage() {
    var inputText by remember { mutableStateOf("") }
    val todoList = remember { mutableStateListOf<String>() }

    Column(modifier = Modifier.padding(20.dp)) {
        TextField(
            value = inputText,
            onValueChange = { inputText = it },
            label = { Text("输入待办事项") }
        )
        Spacer(modifier = Modifier.height(12.dp))

        Button(onClick = {
            if(inputText.isNotBlank()){
                todoList.add(inputText)
                inputText = ""
            }
        }) {
            Text("添加待办")
        }
        Spacer(modifier = Modifier.height(16.dp))

        if(todoList.isEmpty()){
            Text("暂无待办,请添加任务")
        }else{
            LazyColumn {
                items(todoList){ item ->
                    Row(modifier = Modifier.padding(vertical = 4.dp)) {
                        Text("· $item")
                        Spacer(modifier = Modifier.width(10.dp))
                        Button(onClick = { todoList.remove(item) }) {
                            Text("删除")
                        }
                    }
                }
            }
        }
    }
}

答案与解析

解析:每行套Row横向布局,增加删除按钮;点击后调用 remove 删除列表元素,mutableStateListOf自动触发重组刷新列表。

五、本课小结

  1. if条件渲染:在可组合函数中直接分支渲染UI;
  2. LazyColumn:滚动懒加载列表,大数据优先选用;
  3. items 遍历集合生成列表项;
  4. 列表状态优先使用 mutableStateListOf ,增删自动触发重组。

下一课:rememberSaveable,页面旋转/系统重建保留状态。

相关推荐
ai2work1 小时前
ch12 系统能力接入:TTS、剪贴板、分享、文件选择器
kotlin
Rabitebla1 小时前
【Linux系统编程】 指令(二):一条路径是怎么定位到文件的
linux·c++·笔记·学习·算法
小贺儿开发2 小时前
Unity 结合百度AI开放平台 手写文字识别
人工智能·科技·学习·unity·云服务·文字识别·手写文字
传奇开心果编程2 小时前
【SwiftUI入门练中学】第1课 从零开始
学习·ui·ios·swiftui·swift
是隼人2 小时前
buuctf-pwn ciscn_2019_sw_1(32位只有一次格式化机会)题解(学习过程持续更新)
c语言·学习·安全·pwn入门·ctf入门
传奇开心果编程2 小时前
【Jetpack Compose基础语法学与练】第9课 SideEffect副作用 + LaunchedEffect,处理异步任务和生命周期
android·学习·ui·kotlin·android jetpack
传奇开心果编程2 小时前
【ArkUI 练中学】第14课:应用性能优化实战
学习·ui·华为·harmonyos
PNP Robotics3 小时前
【PNP具身解读】GPT6 Astra:具身智能新范式,大模型 + Franka机器人快速落地验证一、GPT6 Astra 背后的布局、数据与具身方向
人工智能·学习·机器学习·机器人
小李不想当小白3 小时前
PCB结构与组成(PCB设计入门学习笔记)
经验分享·笔记·单片机·嵌入式硬件·学习·pcb工艺·pcb