Flutter中如何对late修饰的变量执行算术运算?
问题原因与正确实现方案
核心问题根源
你遇到的所有报错和所谓的方案局限性,本质是两个错误导致的:
- 对
late关键字的特性认知错误,late本身完全支持后续调用变量做算术运算 - 代码中存在同名变量覆盖问题:你已经在类顶部声明了全局的
late AnimationController _controller;,但在animate()方法中又重新声明了一个局部的AnimationController _controller,导致类全局的_controller从未被赋值,后续调用时自然触发late未初始化的报错。
正确修改步骤
- 保留类顶部的
late AnimationController _controller;声明即可,不需要改为可空类型 - 修改
animate()方法,去掉局部变量的类型声明,直接给类全局的_controller赋值 - 算术运算时不需要多余的
!强制解包:AnimationController.value本身就是非空的double类型,不存在空值风险 dispose和其他方法调用_controller时也不需要多余的空判断,你已经在initState里先调用了animate()赋值,符合late变量的使用要求
修改后的完整可运行代码
import 'dart:math'; import 'package:flutter/material.dart'; class HomeScreen extends StatefulWidget { @override _HomeScreenState createState() => _HomeScreenState(); } class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateMixin { int leftDice = 1, rightDice = 1; Random random = Random(); late AnimationController _controller; @override void initState() { super.initState(); animate(); print("Init called"); } @override void dispose() { _controller.dispose(); super.dispose(); } void animate() { print("Animate called"); // 去掉局部变量声明,直接给类层面的_controller赋值 _controller = AnimationController(vsync: this, duration: Duration(seconds: 1)); _controller.addListener(() { setState(() {}); }); _controller.addStatusListener((status) { if (status == AnimationStatus.completed) { print("Completed"); _controller.reverse(); } }); } void roll() { _controller.forward(); setState(() { leftDice = random.nextInt(6) + 1; rightDice = random.nextInt(6) + 1; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Dicee"), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Row( children: [ Expanded( child: Padding( padding: EdgeInsets.all(15), child: GestureDetector( onDoubleTap: roll, child: Image( // 去掉多余的强制解包,直接使用value计算即可 height: 200 - _controller.value * 200, image: AssetImage('assets/images/dice-$leftDice.png'), ), ), )), Expanded( child: Padding( padding: EdgeInsets.all(15), child: GestureDetector( onDoubleTap: roll, child: Image( image: AssetImage('assets/images/dice-$rightDice.png'), ), ), )) ], ), ElevatedButton(onPressed: roll, child: Text("Roll Dice")) ], ), ), ); } }
对原有三个方案的误区纠正
- 方案1的
late声明本身完全可用,你之前的报错是变量未被赋值导致的,和late关键字无关 - 方案2确实不可用:类实例初始化阶段
this还未完成构造,无法直接用来初始化AnimationController - 方案3的问题是你把变量声明在了initState内部变成了局部变量,正确用法是变量声明在类层面,仅在initState(或其调用的方法)中赋值,完全可以被类内所有方法访问
内容的提问来源于stack exchange,提问作者UTPAL GAURAV
相关产品推荐
相关产品推荐

