compose编码01- 实现类似AbsListView 的界面-加载更多

  • 使用compose 实现类似AbsListView 的界面
  • 理解:不需要setAdapter. compose编程与早期的xml方式为何差别这么大
  • 理解AbsListViewActivity.kt的设计思路
  • 不需要findViewById
  • 注解加在函数前,告诉框架这是 UI

Compose = 框架/工具包(名词)
Compose 是 Google 推出的 UI 框架,类似于"装修公司的工具箱"。

Composable = 函数/组件(形容词)
Composable 是 Compose 框架中的 UI 组件/函数,类似于"工具箱里的工具"。

先上图,后看代码AbsListViewActivity.kt

数据初始化
   
数据初始化+更多完成
加载更多

设计介绍

该代码是一个基于 Jetpack Compose 开发的 Android 列表/网格展示示例(AbsListViewActivity),核心功能是实现可切换展示模式、支持增删改查、加载更多、下拉刷新、状态管理的列表/网格组件,整体遵循 MVVM 架构模式。

用户点击按钮 → View 调用 ViewModel 方法 → ViewModel 修改 StateFlow 状态 → View 通过 collectAsState 自动感知变化 → 界面自动重绘

Model:数据、业务逻辑、网络 / 本地数据源
View:纯 UI 界面,只负责展示、接收用户点击事件,不存业务逻辑 ---View 层(对应代码:Compose UI 部分)---MVVM 中间枢纽,完全不依赖 View
ViewModel:连接 View 和 Model,持有状态、处理业务,不持有 View 引用 核心特征:单向数据流、View 被动响应状态、View 不直接操作数据、无 View 持有、解耦。---Model 层(隐含在 ViewModel 内);Model 就是数据源与数据实体;实体:List<String> 列表数据

一、核心架构与角色

代码分为三大核心部分,符合 MVVM 设计思想:

组件 作用
AbsListViewActivity 入口 Activity,负责设置 Compose 内容、承载 UI 容器
AbsListViewModel 核心 viewModel,管理数据、状态逻辑(加载、增删、切换模式等)
Composable 函数 纯 UI 展示层(AbsListViewDemo/DataItemCard),响应式展示 viewModel 状态

二、核心功能拆解

1. 数据管理(ViewModel 核心能力)

ViewModel 封装了所有数据和状态逻辑,通过 StateFlow 实现数据响应式更新:

  • 基础数据操作
    • addItem():新增一条数据项(计数器自增);
    • deleteItem(item):删除指定数据项;
    • clearAll():清空所有数据;
    • toggleMode():切换「列表/网格」展示模式。
  • 加载相关逻辑
    • 初始加载:loadInitialData() 模拟网络请求(延迟 1.5s),加载 10 条初始数据;
    • 加载更多:loadMore() 模拟滚动到底部触发的网络请求(延迟 1s),每次加载 5 条新数据;
    • 刷新数据:refreshData() 清空现有数据后重新执行初始加载,实现「下拉刷新」核心逻辑;
  • 状态管理
    • _dataList:存储列表数据(响应式);
    • _isGridMode:标记当前是列表/网格模式;
    • _loading:标记是否正在加载(加载更多/刷新);
    • _initialLoading:标记是否是「首次初始加载」(区分首次加载和加载更多)。

2. UI 展示与交互(Composable 核心)

AbsListViewDemo 是核心 UI 组件,响应式监听 ViewModel 状态并渲染:

  • 顶部操作区
    • 标题:「AbsListView Compose 示例」;
    • 功能按钮:添加数据、清空数据、切换列表/网格模式、刷新数据(刷新按钮加载时禁用);
    • 数据统计卡片:展示当前数据条数,加载中显示「加载状态+进度条」。
  • 状态适配展示
    • 首次加载中:全屏显示加载动画+提示文字(「加载数据中...」);
    • 空数据状态:全屏显示空状态图标+提示(「暂无数据」);
    • 有数据状态:根据 isGridMode 切换 LazyColumn(列表)/LazyVerticalGrid(网格,3列)。
  • 滚动加载更多
    • 监听 LazyListState 的滚动状态,当滚动到底部且非加载状态时,自动触发 loadMore()
    • 加载中时,列表/网格底部显示「加载更多+进度条」提示。
  • 数据项组件(DataItemCard)
    • 每个数据项封装为卡片,显示文本内容;
    • 右侧带删除按钮,点击触发 deleteItem() 删除当前项。

3. 辅助能力

  • 预览支持@PreviewScreenSizes 注解支持多屏幕尺寸预览;
  • 协程管理:通过 viewModelScope(ViewModel 生命周期)、rememberCoroutineScope(Composable 生命周期)管理异步操作;
  • Material3 风格:基于 Material3 组件(Surface/Card/Button/CircularProgressIndicator)实现样式,适配主题色。

三、核心流程示例

  1. 页面启动 → ViewModel 初始化 → 执行 loadInitialData() → 显示「初始加载中」;
  2. 初始数据加载完成 → 渲染列表/网格(默认列表模式);
  3. 用户滚动到底部 → 触发 loadMore() → 底部显示「加载更多」→ 加载完成后追加数据;
  4. 用户点击「切换到网格」→ isGridMode 变为 true → UI 切换为 3 列网格;
  5. 用户点击「刷新数据」→ 清空数据 → 重新执行初始加载 → 显示加载状态 → 加载完成后展示新数据;
  6. 用户点击数据项删除按钮 → 移除该数据项 → UI 自动刷新。

四、核心亮点

  1. 响应式状态管理:通过 collectAsState() 监听 StateFlow,状态变化自动驱动 UI 刷新;
  2. 状态边界清晰:ViewModel 负责业务逻辑,UI 层只负责渲染,符合「单向数据流」;
  3. 友好的用户体验:区分首次加载/加载更多/空数据状态,加载过程有明确的视觉反馈;
  4. 可复用性:数据项封装为独立 DataItemCard,便于复用和修改;
  5. 生命周期安全:使用 viewModelScope 确保异步操作跟随 ViewModel 生命周期,避免内存泄漏。

AbsListViewActivity.kt

package com.younghare.qqhelper

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Info
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.PreviewScreenSizes
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch


class AbsListViewActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            // 直接使用 MaterialTheme
            MaterialTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    AbsListViewDemo()
                }
            }
        }
    }
}

// ============================================
// ViewModel - 管理数据和状态
// ============================================
class AbsListViewModel : ViewModel() {

    private val _dataList = MutableStateFlow<List<String>>(emptyList())
    val dataList: StateFlow<List<String>> = _dataList

    private val _isGridMode = MutableStateFlow(false)
    val isGridMode: StateFlow<Boolean> = _isGridMode

    // 加载状态
    private val _loading = MutableStateFlow(false)
    val loading: StateFlow<Boolean> = _loading

    // ✅ 新增:初始加载状态(用于区分首次加载和加载更多)
    private val _initialLoading = MutableStateFlow(true)
    val initialLoading: StateFlow<Boolean> = _initialLoading

    private var counter = 0

    init {
        // ✅ 模拟网络请求加载初始数据
        viewModelScope.launch {
            loadInitialData()
        }
    }

    // ✅ 新增:模拟网络请求加载初始数据
    private suspend fun loadInitialData() {
        _initialLoading.value = true
        _loading.value = true

        try {
            // 模拟网络延迟 1500ms(让用户看到加载效果)
            delay(1500)

            val initialData = (1..10).map { "项目 $it" }
            _dataList.value = initialData
            counter = 10
        } finally {
            _initialLoading.value = false
            _loading.value = false
        }
    }

    fun addItem() {
        counter++
        _dataList.value = _dataList.value + "新项目 $counter"
    }

    fun deleteItem(item: String) {
        _dataList.value = _dataList.value.filter { it != item }
    }

    fun clearAll() {
        _dataList.value = emptyList()
        // 清空后重置计数器(可选)
        // counter = 0
    }

    fun toggleMode() {
        _isGridMode.value = !_isGridMode.value
    }

    // 模拟网络请求加载更多
    suspend fun loadMore() {
        // 如果正在加载或没有数据,不执行
        if (_loading.value || _dataList.value.isEmpty()) return

        _loading.value = true

        try {
            // 模拟网络请求延迟 1000ms
            delay(1000)

            val currentSize = _dataList.value.size
            val newItems = (currentSize + 1..currentSize + 5).map { "加载项目 $it" }
            _dataList.value = _dataList.value + newItems
        } finally {
            _loading.value = false
        }
    }

    // ✅ 新增:刷新数据(重新加载)
    fun refreshData() {
        viewModelScope.launch {
            // 清空现有数据
            _dataList.value = emptyList()
            // 重新加载
            loadInitialData()
        }
    }
}

// ============================================
// UI Composable 函数
// ============================================
@PreviewScreenSizes
@Composable
fun AbsListViewDemo(
    viewModel: AbsListViewModel = viewModel()  //viewModel() 检测到当前在 Activity 中 创建(或复用)AbsListViewModel 实例

    // 或 viewModel: AbsListViewModel = viewModel<AbsListViewModel>()
) {
    val dataList by viewModel.dataList.collectAsState()
    val isGridMode by viewModel.isGridMode.collectAsState()
    val loading by viewModel.loading.collectAsState()
    val initialLoading by viewModel.initialLoading.collectAsState()  // ✅ 获取初始加载状态

    val listState = rememberLazyListState()
    val coroutineScope = rememberCoroutineScope()

    // 检测滚动到底部触发加载更多
    LaunchedEffect(listState) {
        snapshotFlow { listState.layoutInfo }
            .collect { layoutInfo ->
                val visibleItems = layoutInfo.visibleItemsInfo
                if (visibleItems.isNotEmpty()) {
                    val lastVisibleIndex = visibleItems.last().index
                    val totalItems = layoutInfo.totalItemsCount
                    // 滚动到底部且不处于加载状态
                    if (lastVisibleIndex >= totalItems - 1 && totalItems > 0 && !loading) {
                        coroutineScope.launch {
                            viewModel.loadMore()
                        }
                    }
                }
            }
    }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp)
    ) {
        // 标题
        Text(
            text = "AbsListView Compose 示例",
            style = MaterialTheme.typography.headlineSmall,
            modifier = Modifier
                .fillMaxWidth()
                .padding(bottom = 16.dp),
            textAlign = androidx.compose.ui.text.style.TextAlign.Center
        )

        // 操作按钮行
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(bottom = 16.dp),
            horizontalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            Button(
                onClick = { viewModel.addItem() },
                modifier = Modifier.weight(1f)
            ) {
                Text("添加数据")
            }

            Button(
                onClick = { viewModel.clearAll() },
                modifier = Modifier.weight(1f),
                colors = ButtonDefaults.buttonColors(
                    containerColor = MaterialTheme.colorScheme.error
                )
            ) {
                Text("清空数据")
            }

            Button(
                onClick = { viewModel.toggleMode() },
                modifier = Modifier.weight(1f)
            ) {
                Text(if (isGridMode) "切换到列表" else "切换到网格")
            }
        }

        // ✅ 新增:刷新按钮
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(bottom = 8.dp),
            horizontalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            Button(
                onClick = { viewModel.refreshData() },
                modifier = Modifier.fillMaxWidth(),
                enabled = !loading  // 加载时禁用
            ) {
                Text(if (loading) "加载中..." else "🔄 刷新数据")
            }
        }

        // 数据统计信息
        Card(
            modifier = Modifier
                .fillMaxWidth()
                .padding(bottom = 8.dp),
            colors = CardDefaults.cardColors(
                containerColor = MaterialTheme.colorScheme.primaryContainer
            )
        ) {
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(12.dp),
                horizontalArrangement = Arrangement.SpaceBetween,
                verticalAlignment = Alignment.CenterVertically
            ) {
                Text(
                    text = "数据数量: ${dataList.size} 项",
                    style = MaterialTheme.typography.bodyMedium
                )
                // 显示加载状态
                if (loading) {
                    Row(
                        horizontalArrangement = Arrangement.spacedBy(8.dp),
                        verticalAlignment = Alignment.CenterVertically
                    ) {
                        CircularProgressIndicator(
                            modifier = Modifier.size(16.dp),
                            strokeWidth = 2.dp
                        )
                        Text(
                            text = if (initialLoading) "初始化加载中..." else "加载中...",
                            style = MaterialTheme.typography.bodySmall,
                            color = MaterialTheme.colorScheme.primary
                        )
                    }
                }
            }
        }

        // 内容区域:列表/网格 或 空状态
        // ✅ 处理初始加载状态
        if (initialLoading) {
            // 初始加载中的全屏占位
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(32.dp),
                contentAlignment = Alignment.Center
            ) {
                Column(
                    horizontalAlignment = Alignment.CenterHorizontally,
                    verticalArrangement = Arrangement.spacedBy(16.dp)
                ) {
                    CircularProgressIndicator(
                        modifier = Modifier.size(64.dp),
                        strokeWidth = 4.dp
                    )
                    Text(
                        text = "加载数据中...",
                        style = MaterialTheme.typography.headlineSmall,
                        color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
                    )
                    Text(
                        text = "正在从服务器获取数据",
                        style = MaterialTheme.typography.bodyMedium,
                        color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.4f)
                    )
                }
            }
        } else if (dataList.isEmpty()) {
            // 空状态视图
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(32.dp),
                contentAlignment = Alignment.Center
            ) {
                Column(
                    horizontalAlignment = Alignment.CenterHorizontally,
                    verticalArrangement = Arrangement.spacedBy(16.dp)
                ) {
                    Icon(
                        imageVector = Icons.Default.Info,
                        contentDescription = "空状态",
                        modifier = Modifier.size(64.dp),
                        tint = MaterialTheme.colorScheme.primary.copy(alpha = 0.5f)
                    )
                    Text(
                        text = "暂无数据",
                        style = MaterialTheme.typography.headlineSmall,
                        color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
                    )
                    Text(
                        text = "点击\"添加数据\"按钮添加项目",
                        style = MaterialTheme.typography.bodyMedium,
                        color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.4f)
                    )
                }
            }
        } else {
            // 使用 Box 包裹列表,以便在列表底部显示加载提示
            Box(modifier = Modifier.fillMaxSize()) {
                if (isGridMode) {
                    LazyVerticalGrid(
                        columns = GridCells.Fixed(3),
                        modifier = Modifier.fillMaxSize(),
                        horizontalArrangement = Arrangement.spacedBy(8.dp),
                        verticalArrangement = Arrangement.spacedBy(8.dp)
                    ) {
                        items(dataList) { item ->
                            DataItemCard(
                                item = item,
                                onDelete = { viewModel.deleteItem(item) }
                            )
                        }
                        // 在网格模式下显示加载底部
                        if (loading && !initialLoading) {
                            item {
                                Box(
                                    modifier = Modifier
                                        .fillMaxWidth()
                                        .padding(16.dp),
                                    contentAlignment = Alignment.Center
                                ) {
                                    Row(
                                        horizontalArrangement = Arrangement.spacedBy(8.dp),
                                        verticalAlignment = Alignment.CenterVertically
                                    ) {
                                        CircularProgressIndicator(
                                            modifier = Modifier.size(20.dp),
                                            strokeWidth = 2.dp
                                        )
                                        Text(
                                            text = "加载更多...",
                                            style = MaterialTheme.typography.bodyMedium,
                                            color = MaterialTheme.colorScheme.primary
                                        )
                                    }
                                }
                            }
                        }
                    }
                } else {
                    LazyColumn(
                        state = listState,
                        modifier = Modifier.fillMaxSize(),
                        verticalArrangement = Arrangement.spacedBy(4.dp)
                    ) {
                        items(dataList) { item ->
                            DataItemCard(
                                item = item,
                                onDelete = { viewModel.deleteItem(item) }
                            )
                        }
                        // 在列表底部显示加载提示
                        if (loading && !initialLoading) {
                            item {
                                Box(
                                    modifier = Modifier
                                        .fillMaxWidth()
                                        .padding(16.dp),
                                    contentAlignment = Alignment.Center
                                ) {
                                    Row(
                                        horizontalArrangement = Arrangement.spacedBy(8.dp),
                                        verticalAlignment = Alignment.CenterVertically
                                    ) {
                                        CircularProgressIndicator(
                                            modifier = Modifier.size(20.dp),
                                            strokeWidth = 2.dp
                                        )
                                        Text(
                                            text = "加载更多...",
                                            style = MaterialTheme.typography.bodyMedium,
                                            color = MaterialTheme.colorScheme.primary
                                        )
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

// ============================================
// 数据项卡片组件
// ============================================
@Composable
fun DataItemCard(
    item: String,
    onDelete: () -> Unit
) {
    Card(
        modifier = Modifier.fillMaxWidth(),
        elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
    ) {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(12.dp),
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically
        ) {
            Text(
                text = item,
                style = MaterialTheme.typography.bodyLarge,
                modifier = Modifier.weight(1f)
            )

            IconButton(
                onClick = onDelete,
                modifier = Modifier.size(32.dp)
            ) {
                Icon(
                    imageVector = Icons.Default.Close,
                    contentDescription = "删除",
                    tint = MaterialTheme.colorScheme.error
                )
            }
        }
    }
}

为何不需要setAdapter. compose编程与早期的xml方式为何差别这么大

非常好的问题!让我详细解释这些关键概念:

1. 是否使用了 AbsListView?

答案:没有使用 AbsListView

您的代码使用的是 Jetpack ComposeLazyColumnLazyVerticalGrid,它们不是 AbsListView 的替代品,而是完全不同的 UI 框架。

对比项 XML 方式 (AbsListView) Compose 方式
基类 AbsListView (ListView/GridView) LazyColumn / LazyVerticalGrid
UI 框架 Android View System Jetpack Compose
适配器 需要 Adapter (如 ArrayAdapter) 不需要,直接使用 items()
更新方式 adapter.notifyDataSetChanged() 状态变化自动重组
代码风格 命令式 声明式
出现时间 Android 1.0 (2008) Android 2019 年推出

2. 为什么不需要 setAdapter?

XML 方式(需要 Adapter)

// XML 方式 - 需要 Adapter
class MyActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        val listView = findViewById<ListView>(R.id.listView)
        val data = listOf("项目1", "项目2", "项目3")
        
        // ❗必须创建 Adapter
        val adapter = ArrayAdapter<String>(
            this,
            android.R.layout.simple_list_item_1,
            data
        )
        
        // ❗必须设置 Adapter
        listView.adapter = adapter
        
        // 更新数据需要手动通知
        data.add("新项目")
        adapter.notifyDataSetChanged()  // ❗必须手动刷新
    }
}

Compose 方式(不需要 Adapter)

// Compose 方式 - 不需要 Adapter
@Composable
fun MyScreen() {
    // 数据直接作为状态
    var dataList by remember { mutableStateOf(listOf("项目1", "项目2", "项目3")) }
    
    // ❗直接使用 LazyColumn,不需要 Adapter
    LazyColumn {
        items(dataList) { item ->  // ❗直接传入数据
            Text(item)
        }
    }
    
    // 更新数据:直接修改状态,UI 自动更新!
    Button(onClick = { 
        dataList = dataList + "新项目"  // ❗不需要 notifyDataSetChanged()
    }) {
        Text("添加")
    }
}

3. 为什么差别这么大?

核心理念不同

特性 XML 方式 (命令式) Compose 方式 (声明式)
编程范式 命令式:告诉"怎么做" 声明式:告诉"是什么"
UI 更新 手动调用方法更新 状态变化自动更新
数据绑定 Adapter 作为桥梁 直接使用状态
代码量 多(需要 Adapter、ViewHolder 等) 少(直接描述 UI)

对比示例:添加数据

XML 方式(命令式):

// 1. 定义数据
private val dataList = mutableListOf("项目1", "项目2")
// 2. 创建 Adapter
private lateinit var adapter: ArrayAdapter<String>
// 3. 设置 Adapter
adapter = ArrayAdapter(this, R.layout.item, dataList)
listView.adapter = adapter

// 4. 添加数据(需要手动通知)
fun addItem() {
    dataList.add("新项目")
    adapter.notifyDataSetChanged()  // ❗必须手动调用
}

Compose 方式(声明式):

// 1. 定义状态
var dataList by remember { mutableStateOf(listOf("项目1", "项目2")) }

// 2. 描述 UI
LazyColumn {
    items(dataList) { item ->
        Text(item)
    }
}

// 3. 添加数据(自动更新)
fun addItem() {
    dataList = dataList + "新项目"  // ✅ 自动更新 UI!
}

4. 架构对比图

┌─────────────────────────────────────────────────────────────┐
│                    XML 方式 (View System)                    │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  数据源 ──→ Adapter ──→ View (ListView/GridView)          │
│              ↑            ↑                                 │
│         notifyDataSetChanged  getView()                     │
│              │            │                                 │
│        手动触发更新    创建/复用 View                        │
│                                                             │
│  特点:                                                     │
│  • 需要 Adapter 做桥梁                                     │
│  • 手动管理 View 复用 (ViewHolder)                         │
│  • 手动通知更新                                            │
│  • 命令式编程                                              │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│                  Compose 方式 (声明式 UI)                    │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  状态 (State) ──→ Composable UI ──→ 自动渲染               │
│       ↑              ↑                                      │
│   修改状态      自动重组                                    │
│       │              │                                      │
│  用户交互       观察状态变化                                │
│                                                             │
│  特点:                                                     │
│  • 不需要 Adapter                                           │
│  • 自动管理渲染                                            │
│  • 状态变化自动更新                                        │
│  • 声明式编程                                              │
└─────────────────────────────────────────────────────────────┘

5. 您的代码中的关键点

// ❗您的代码不需要 Adapter,因为 Compose 自动处理

// 1. 状态(数据源)
private val _dataList = MutableStateFlow<List<String>>(emptyList())
val dataList: StateFlow<List<String>> = _dataList

// 2. 在 Composable 中读取状态
@Composable
fun AbsListViewDemo(viewModel: AbsListViewModel = viewModel()) {
    val dataList by viewModel.dataList.collectAsState()  // ❗自动订阅
    
    // 3. 直接使用数据(不需要 Adapter)
    LazyColumn {
        items(dataList) { item ->  // ❗直接传入数据
            DataItemCard(item)
        }
    }
}

// 4. 修改数据(自动更新 UI)
fun addItem() {
    _dataList.value = _dataList.value + "新项目"  // ✅ UI 自动重组
}

6. 总结

问题 答案
使用 AbsListView 吗? ❌ 没有,使用的是 Compose 的 LazyColumn/LazyVerticalGrid
为什么不需要 setAdapter? Compose 是声明式框架,状态变化自动更新 UI,不需要 Adapter 作为桥梁
为什么差别这么大? XML 是命令式(告诉怎么做),Compose 是声明式(告诉是什么),编程范式完全不同
哪个更好? Compose 更现代、代码更少、更易维护,但需要学习新的思维方式

简单类比

XML 方式 = 手工做饭(需要洗菜、切菜、炒菜、摆盘每一步都要自己操作)

Compose 方式 = 点外卖(告诉外卖平台要什么,自动送来)

两者都能吃到饭,但方式完全不同!🍱

希望这个解释能帮您理解为什么 Compose 和传统的 XML 方式差别这么大!如果还有疑问,欢迎继续提问!😊

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容