为什么 `DateTime.add(const Duration(days: 1)` 添加 *Seconds* 而不是 Days?

Why is `DateTime.add(const Duration(days: 1)` adding *Seconds* instead of Days?

我有一个 Text() 小部件,它将 DateTime 显示为 String。这个 Text() 小部件用 GestureDetecture() 包装,其中 onTap 应该将 DateTime 更新 :

GestureDetector(
            child: File2(
              dateTime: date,
              key: Key(date.toString()),
            ),
            onTap: () {
              setState(() {
                // This is adding seconds not days
                date = date.add(const Duration(days: 1));
              });
            },
          ),

但是,尽管我这样做了,但日期没有更新一天:

date = date.add(const Duration(days: 1));

然而,它正在更新几秒钟。为什么它没有 1 天更新?

我试过的: 使用 Key()

代码:

file_1.dart:

import 'package:flutter/material.dart';

import 'file_2.dart';

void main() {
  runApp(File1());
}

class File1 extends StatefulWidget {
  const File1({Key? key}) : super(key: key);

  @override
  State<File1> createState() => _File1State();
}

class _File1State extends State<File1> {
  @override
  Widget build(BuildContext context) {
    DateTime date = DateTime.now();

    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: GestureDetector(
            child: File2(
              dateTime: date,
              key: Key(date.toString()),
            ),
            onTap: () {
              setState(() {
                // This is adding seconds not days
                date = date.add(const Duration(days: 1));
              });
            },
          ),
        ),
      ),
    );
  }
}

file_2.dart:

import 'package:flutter/material.dart';

class File2 extends StatelessWidget {
  DateTime dateTime;
  File2({Key? key, required this.dateTime}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Text(dateTime.toString());
  }
}

问题

这个错误的发生仅仅是因为你在构建方法的开头有这一行:DateTime date = DateTime.now();.

这是您的代码中发生的工作流程:

  1. 您在构建方法的开头将日期值设置为 DateTime.now()
  2. 当前日期值呈现在您的 UI 中。
  3. 您触发更新日期的功能。
  4. +1 天添加到日期。
  5. 重要提示:第​​ 4 步会触发小部件的重建,因此会再次执行第 1 步。

作为第 5 步的结果,日期值只更新了片刻,但随后 DateTime.now() 在 UI 中呈现。

解决方案

在您的状态 class 而不是构建方法中启动 date 值。这样,您的 date 值将不会被 Widget 重建覆盖:

class _File1State extends State<File1> {
  DateTime date = DateTime.now(); // <-- Initiate the value here
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: GestureDetector(
            child: File2(
              dateTime: date,
              key: Key(date.toString()),
            ),
            onTap: () {
              setState(() {
                // This is adding seconds not days
                date = date.add(const Duration(days: 1));
              });
            },
          ),
        ),
      ),
    );
  }
}