Flutter学习点统计

6 阅读3分钟

一、rowItems.asMap().entries.map的使用

rowItems.asMap().entries.map 是Dart中处理列表的一种常用方式,我来解释它的含义:

  1. rowItems.asMap()

    • 将列表转换为一个Map,其中key是元素的索引,value是元素本身
    • 例如:['a', 'b', 'c'].asMap() 会变成 {0: 'a', 1: 'b', 2: 'c'}
  2. .entries

    • 获取Map的所有键值对(entry)
    • 每个entry包含key(索引)和value(元素值)
  3. .map()

    • 对每个entry进行转换
    • 这里我们将每个entry转换为一个ItemWidget
  4. 完整解释

    • rowItems.asMap().entries.map() 让我们可以同时访问元素的索引和值
    • 在回调函数中,entry.key是索引,entry.valueItemModel对象
    • 这样我们就可以在创建ItemWidget时,同时传递项目数据和它在行中的位置索引

这种写法比直接使用rowItems.map()更强大,因为:

  • 可以直接获取元素的索引,而不需要额外维护计数器
  • 代码更简洁,更函数式
  • 适用于需要同时处理索引和值的场景
 children: rowItems.asMap().entries.map(
                        (entry) {
                          final itemIndex = entry.key;
                          final item = entry.value;
                          return ItemWidget(
                            item: item,
                            onTap: () {
                              if (widget.onItemClick != null) {
                                widget.onItemClick!(pageIndex, itemIndex, item);
                              }
                            },
                          );
                        }
                      ).toList()

二、自定义页面点击事件数据回传

  1. ItemWidget中创建事件 在自定义widget中,创建回调函数,并调用。
 /// 点击回调函数
  final Function()? onTap;
   // 上图 (带点击事件)
  GestureDetector(
    onTap: onTap,
    child: ClipRRect(
      borderRadius: BorderRadius.circular(borderRadius),
      child: Image.network(
        item.imageUrl,
        width: imageWidth,
        height: imageHeight,
        fit: BoxFit.cover,
      ),
    ),
  ),
  
  1. 在自定义的SlidingArea进一层中处理
/// 定义点击回调函数类型
/// rowIndex: 行索引
/// itemIndex: 项目索引
/// item: 点击的项目数据  ios 的 block. swift的闭包
typedef ItemClickCallback = void Function(int rowIndex, int itemIndex, ItemModel item);

在内部声明一下
/// 项目点击回调
final ItemClickCallback? onItemClick;

//显示widget的同时调用
return ItemWidget(
        item: item,
        onTap: () {
          if (widget.onItemClick != null) {
            widget.onItemClick!(pageIndex, itemIndex, item);
          }
        },
      );
      
      


  1. 在HomePage中接收数据
Text(
       _clickInfo,
       style: const TextStyle(fontSize: 16, color: Colors.blue),
       maxLines: 1,
       overflow: TextOverflow.ellipsis,
     ),
 //最终在page页面,并更新数据
 SlidingArea(
       data: data,
       onItemClick: (rowIndex, itemIndex, item) {
         setState(() {
           _clickInfo = '点击了第${rowIndex + 1}行第${itemIndex + 1}个项目\n'
               '标题: ${item.title}\n'
               '图片URL: ${item.imageUrl}';
         });
       },
     ),

三、State的作用

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
    Widget build(BuildContext context) {
        ............
    }
}

State是Flutter框架中实现有状态组件的核心概念,它有以下几个重要作用:

  1. 存储和管理可变数据

    • 在您的例子中,_clickInfo变量就存储在State
    • 当数据变化时,可以通过setState()触发UI重建
  2. 维持组件生命周期

    • State对象在组件的整个生命周期中保持存在
    • 即使组件重建,State中的数据也会保留
  3. 提供生命周期钩子

    • initState()dispose()等方法
    • 允许在组件创建、更新和销毁时执行特定代码
  4. 响应用户交互

    • 处理用户事件(如点击)
    • 更新UI状态

为什么要这样写:

class _HomePageState extends State<HomePage> 这种写法是Flutter中实现有状态组件的标准模式,原因如下:

  1. 分离关注点

    • HomePage(Widget)负责定义组件的配置和参数
    • _HomePageState(State)负责管理组件的状态和行为
  2. 封装性

    • 下划线前缀_表示这是一个私有类,只在当前文件中可见
    • 防止外部直接访问或修改状态
  3. 类型安全

    • extends State<HomePage>明确指定这个State属于哪个Widget
    • 确保类型安全和IDE智能提示