Flutter+Supabase实现ListView.builder跳转详情页并传参
解决ListView.builder跳转详情页传递数据的方案
1. 改造详情页,添加数据接收能力
让PageDetail通过构造函数接收列表项数据,示例如下:
class PageDetail extends StatelessWidget { // 定义接收数据的变量 final Map<String, dynamic> itemData; // 构造函数,强制传入数据 const PageDetail({super.key, required this.itemData}); @override Widget build(BuildContext context) { // 在详情页中直接使用itemData渲染内容 return Scaffold( appBar: AppBar(title: Text(itemData['date'])), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('日期: ${itemData['date']}'), Text('时间: ${itemData['heure']}'), // 根据数据库字段添加其他展示内容 ], ), ), ); } }
2. 在列表点击事件中传递对应索引的数据
回到列表页面,修改InkWell的onTap回调,跳转时传入当前列表项的数据:
// 替换原有的onTap代码 onTap: () => Navigator.push( context, MaterialPageRoute( builder: (context) => PageDetail(itemData: items[index]), ), ),
3. 进阶优化:用实体类替代Map(可选)
如果数据结构固定,推荐创建实体类封装数据,提升代码可读性与类型安全性:
第一步:创建实体类
class MyItem { final String id; final String date; final String heure; // 根据数据库表结构添加其他字段 MyItem({ required this.id, required this.date, required this.heure, }); // 从Map转换为实体类的方法 factory MyItem.fromMap(Map<String, dynamic> map) { return MyItem( id: map['id'] as String, date: map['date'] as String, heure: map['heure'] as String, ); } }
第二步:转换Stream中的数据类型
修改Supabase流,将Map列表转为实体类列表:
// 更新流定义 final _mySupabaseTable = Supabase.instance.client .from('xxx') .stream(primaryKey: ['id']) .order('id', ascending: false) .map((maps) => maps.map(MyItem.fromMap).toList()); // 对应修改StreamBuilder的泛型 StreamBuilder<List<MyItem>>( stream: _mySupabaseTable, builder: (context, snapshot) { if (!snapshot.hasData) { return const Center(child: CircularProgressIndicator()); } final items = snapshot.data!; return ListView.builder( itemCount: items.length, itemBuilder: (context, index) { final currentItem = items[index]; return InkWell( onTap: () => Navigator.push( context, MaterialPageRoute( builder: (context) => PageDetail(item: currentItem), ), ), child: Card( child: Padding( padding: const EdgeInsets.all(8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ ListTile( title: Text('${currentItem.date} / ${currentItem.heure}', style: const TextStyle(fontSize: 12.0, color: Colors.grey),), trailing: const Icon(Icons.arrow_forward_ios), ), ], ), ), ), ); }, ); }, )
第三步:修改详情页接收实体类
class PageDetail extends StatelessWidget { final MyItem item; const PageDetail({super.key, required this.item}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(item.date)), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('日期: ${item.date}'), Text('时间: ${item.heure}'), ], ), ), ); } }
核心逻辑是通过详情页的构造函数接收参数,在跳转时传入对应索引的列表数据,两种方式都能实现需求,实体类方案更适合中大型项目。
内容的提问来源于stack exchange,提问作者mbrd
相关产品推荐
相关产品推荐

