You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)),
              ],
          ),
        ),
      ),
    );
  }
}

错误原因

  1. 返回数据未正确接收:当前通过ModalRoute.of(context)?.settings.arguments获取参数,仅在首次进入Home页面时有效;从location页面pop返回时,该参数不会自动更新,导致data未被新数据覆盖。
  2. 空值未处理:直接使用data["isday"]时未判断是否为null,且强制类型转换as Map未处理参数为null的场景,触发类型不匹配错误。
  3. 冗余初始化: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 20:25:03