Flutter 中使用pushNamed传参生成月份对应天数列表的实现问题
路由传参与月份天数列表实现的修正方案
核心问题梳理
- 天数计算逻辑的存放位置错误:在首页点击事件中编写的
List.generate(31, (index) => index)既没有接收返回值,也没有将生成的内容传递到目标路由,执行后没有任何实际效果;跳转到详情页时虽然传入了Months实例,但详情页本身没有实现天数计算逻辑,最终只能显示传入的id值。 - 详情页渲染逻辑缺失:当前详情页仅实现了单个展示id的列表项,完全没有根据传入的月份id生成对应天数列表的代码逻辑。
- switch判断写法错误:原代码中
switch (Months.id)直接引用类的静态属性,而实际每个月份的id是存储在Months实例中的,这种写法根本无法获取到正确的id值。 - 传参逻辑冗余:跳转传参时重新创建了一个仅携带id的Months对象,完全可以直接引用当前列表中已存在的Months实例传递,减少重复代码。
修正实现步骤
1. 简化首页的跳转传参逻辑
把首页点击事件里无效的setState包裹的switch逻辑全部删掉,跳转时直接传递基础类型的月份id即可,不需要传自定义对象,减少类型不匹配的问题:
onTap: () { // 直接传递当前点击月份的id作为路由参数 Navigator.pushNamed( context, "/days", arguments: _monthoftheyear[index].id, ); }
- 传参时尽量传递基础类型数据,复杂计算逻辑放到目标页面执行,避免传参时做冗余操作导致的逻辑混乱。
2. 实现详情页的天数计算与渲染逻辑
先明确闰年判断规则:
闰年判断通用规则:年份能被4整除但不能被100整除,或能被400整除的为闰年,此时二月有29天,否则为28天。
在详情页内部封装一个根据月份id生成天数列表的工具方法,替代零散的switch判断,逻辑更清晰:
List<String> _getDayListByMonthId(int monthId) { // 获取当前年份用于判断二月天数 int currentYear = DateTime.now().year; int februaryDay = (currentYear % 4 == 0 && currentYear % 100 != 0) || (currentYear % 400 == 0) ? 29 : 28; // 用映射表对应每个月的总天数,比多分支switch更简洁 Map<int, int> monthDayMap = { 1:31, 2:februaryDay, 3:31, 4:30, 5:31, 6:30, 7:31, 8:31, 9:30,10:31,11:30,12:31 }; // 根据月份id取对应总天数,生成从1开始计数的天数列表 int totalDay = monthDayMap[monthId] ?? 0; return List.generate(totalDay, (index) => "Day ${index + 1}"); }
接着调整详情页的build方法,接收路由传入的id,调用工具方法生成列表后用ListView渲染:
class Days extends StatelessWidget { @override Widget build(BuildContext context) { // 接收路由传入的int类型月份id,注意做类型转换 final int monthId = ModalRoute.of(context).settings.arguments as int; // 调用方法生成对应月份的天数列表 final List<String> dayList = _getDayListByMonthId(monthId); return Scaffold( appBar: AppBar( title: Text("月份$monthId 天数列表"), ), body: ListView.builder( itemCount: dayList.length, itemBuilder: (context, index) { return ListTile( title: Text(dayList[index]), ); }, ), ); } // 将上面封装的天数生成方法放在当前类内部即可 List<String> _getDayListByMonthId(int monthId) { int currentYear = DateTime.now().year; int februaryDay = (currentYear % 4 == 0 && currentYear % 100 != 0) || (currentYear % 400 == 0) ? 29 : 28; Map<int, int> monthDayMap = { 1:31, 2:februaryDay, 3:31, 4:30, 5:31, 6:30, 7:31, 8:31, 9:30,10:31,11:30,12:31 }; int totalDay = monthDayMap[monthId] ?? 0; return List.generate(totalDay, (index) => "Day ${index + 1}"); } }
补充注意事项
- 一定要在
MaterialApp中配置好/days路由的指向,否则跳转时会出现路由找不到的报错:
MaterialApp( initialRoute: "/", routes: { "/": (context) => Home(), "/days": (context) => Days(), }, )
- 如果坚持要传递自定义的Months对象作为参数,接收时必须做好类型转换:比如传参时传的是Months实例,接收时就要写
final Months monthInfo = ModalRoute.of(context).settings.arguments as Months;,再从实例中取出id做天数计算,不能混用类型导致运行时错误。 - 之前在首页编写的
setState包裹的switch逻辑完全是无效代码:因为计算出来的天数是要在详情页展示的,修改首页的状态不会影响详情页的内容,直接删除即可。
内容的提问来源于stack exchange,提问作者nana
相关产品推荐
相关产品推荐

