Flutter世界时钟应用报错:type 'Null' is not a subtype of type 'bool'
Flutter世界时钟应用:解决
type 'Null' is not a subtype of type 'bool'错误 问题详情
开发世界时钟应用时,从页面栈弹出页面并向主页传递bool类型数据时,触发错误:type 'Null' is not a subtype of type 'bool',错误发生在world_time/pages/home.dart第29行(即data["isday"]的调用处)。
复现步骤
- 运行应用
- 点击编辑图标,搜索并选择带有时区的地点(如Cairo)
- 返回主页时触发上述错误
相关Home页面代码
import 'package:flutter/material.dart'; import 'package:timezone/data/latest.dart' as tz; import 'package:timezone/standalone.dart' as tz1; import 'package:flutter_analog_clock/flutter_analog_clock.dart'; class Home extends StatefulWidget { const Home({super.key}); @override State<Home> createState() => _HomeState(); } class _HomeState extends State<Home> { Map data = {}; @override Widget build(BuildContext context) { data = data.isEmpty ? data = ModalRoute.of(context)?.settings.arguments as Map : data = data; tz.initializeTimeZones(); var detroit = tz1.getLocation(data["url"]); var now = tz1.TZDateTime.now(detroit); return Scaffold( body: Container( decoration: BoxDecoration( gradient: data["isday"] ? const LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Color.fromRGBO(57, 59, 245, 1), Color.fromRGBO(62, 103, 238, 1), Color.fromRGBO(84, 171, 230, 1) ]) : const LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Colors.black, Color.fromRGBO(22, 63, 198, 1), ])), child: SafeArea( child: Column( children: [ const SizedBox(height: 20), const Text("World Clock", style: TextStyle(color: Colors.white, fontSize: 20)), const SizedBox(height: 60), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(data["location"], style: const TextStyle( color: Colors.white, fontSize: 70, fontWeight: FontWeight.w500, shadows: <Shadow>[ Shadow( offset: Offset(3.0, 6.0), color: Color.fromRGBO(0, 0, 0, 0.17647058823529413)) ], )), IconButton(onPressed: () {Navigator.pushNamed(context, "/location");}, icon: Icon(Icons.edit)) ], ), const SizedBox(height: 20), Text(data["date"], style: const TextStyle( color: Colors.white, fontSize: 20, fontWeight: FontWeight.w500)), const SizedBox(height: 40), Padding( padding: const EdgeInsets.symmetric(horizontal: 72), child: AnalogClock( dateTime: now, hourNumberColor: data["isday"] ? Colors.black : Colors.white, hourHandColor: Colors.white, minuteHandColor: Colors.white, secondHandColor: Colors.red, secondHandLengthFactor: 0.8, centerPointColor: null, hourHandWidthFactor: 0.5, dialColor: Colors.black, hourNumbers: const [ '', '', '—', '', '', '|', '', '', '—', '', '', '|' ]), ), const SizedBox(height: 20), Text(data["time"], style: const TextStyle( color: Colors.white, fontSize: 50, fontWeight: FontWeight.w500)), ], ), ), ), ); } }
错误原因
- 返回数据未正确接收:当前通过
ModalRoute.of(context)?.settings.arguments获取参数,仅在首次进入Home页面时有效;从location页面pop返回时,该参数不会自动更新,导致data未被新数据覆盖。 - 空值未处理:直接使用
data["isday"]时未判断是否为null,且强制类型转换as Map未处理参数为null的场景,触发类型不匹配错误。 - 冗余初始化:
tz.initializeTimeZones()在每次build时重复执行,属于无效操作。
解决方案
1. 正确接收返回页面的数据
修改主页跳转至location页面的逻辑,通过async/await获取返回结果并更新状态:
IconButton( onPressed: () async { final result = await Navigator.pushNamed(context, "/location"); if (result != null && result is Map) { setState(() { data = result; }); } }, icon: const Icon(Icons.edit, color: Colors.white), )
2. 安全处理初始参数与空值
将初始参数获取移至initState,并对data["isday"]添加空值兜底:
class _HomeState extends State<Home> { Map data = {}; @override void initState() { super.initState(); // 仅初始化时获取一次初始参数 final args = ModalRoute.of(context)?.settings.arguments; if (args is Map) { data = args; } // 时区初始化仅执行一次 tz.initializeTimeZones(); } @override Widget build(BuildContext context) { // 处理空数据或缺失url的情况 if (data.isEmpty || data["url"] == null) { return const Scaffold( body: Center(child: Text("加载中...", style: TextStyle(color: Colors.white))), ); } var detroit = tz1.getLocation(data["url"]); var now = tz1.TZDateTime.now(detroit); return Scaffold( body: Container( decoration: BoxDecoration( gradient: (data["isday"] ?? false) // 空值时默认false ? const LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Color.fromRGBO(57, 59, 245, 1), Color.fromRGBO(62, 103, 238, 1), Color.fromRGBO(84, 171, 230, 1) ]) : const LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Colors.black, Color.fromRGBO(22, 63, 198, 1), ])), child: SafeArea( child: Column( children: [ // 其余代码保持不变 Padding( padding: const EdgeInsets.symmetric(horizontal: 72), child: AnalogClock( dateTime: now, hourNumberColor: (data["isday"] ?? false) ? Colors.black : Colors.white, // 同样添加空值判断 // 其余时钟属性不变 ), ), // 其余代码不变 ], ), ), ), ); } }
3. 确保location页面传递合法数据
在location页面选择地点后,Navigator.pop传递的Map必须包含非null的isday字段:
// location页面示例代码 Navigator.pop(context, { "url": "所选时区的url", "isday": true, // 确保为bool类型,不能为null "location": "地点名称", "date": "日期", "time": "时间" });
内容的提问来源于stack exchange,提问作者Sanchit Batra
相关产品推荐
相关产品推荐

