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

Flutter Stateful Widget类变量值被意外修改问题咨询

Flutter中Stateful Widget的列表引用异常问题

在Stateful Widget中,我通过widget.variable_name从类的final列表变量初始化本地列表,但删除本地列表中的项时,类变量也同步发生了变化,不符合预期。

问题代码

Test组件代码

import 'package:flutter/material.dart';

class Test extends Stateful Widget {
  const Test({
    required this.fruits
});

  final List<String> fruits;

  static const String routeName = '/test';

  static Route route({required List<String> fruits}){
    return MaterialPageRoute(
      settings: RouteSettings(name: routeName),
      builder: (_) => Test(fruits: fruits,)
    );
  }

  @override
  State<Test> createState() => _TestState();
}

class _TestState extends State<Test> {

  List<String>? _fruits;

  void deleteFruit(name){
    setState((){
      _fruits!.remove(name);
      print("_fruits: ${_fruits}");
      print("widget.fruits: ${widget.fruits}");
    });
  }

  @override
  void initState() {
    super.initState();
    setState(() {
     _fruits = widget.fruits;
     print("Initial fruits: $_fruits");
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Container(
        child: Column(
          children:
          (_fruits != null) ?
          _fruits!.map((e) => ListTile(
            leading: IconButton(
             icon: Icon(Icons.remove),
                onPressed: (){
                    deleteFruit(e);
              }),
            title: Text(e),
            ),
          ).toList() : []
        ),
      ),
    );
  }
}

路由跳转代码

Navigator.pushNamed(context, '/test',arguments: ["apple","mango","orange"]);

实际输出

删除"mango"项后,控制台输出:

_fruits: ["apple","orange"]
widget.fruits: ["apple","orange"] // 预期应为["apple","mango","orange"]

原因分析

这是Dart中引用类型的特性导致的:

  • 列表属于引用类型,_fruits = widget.fruits并没有创建新的列表,只是将_fruits变量指向了widget.fruits对应的同一个内存地址的列表对象。
  • final关键字仅限制widget.fruits变量不能被重新赋值(即不能让它指向其他列表对象),但不限制对列表内部元素的修改。所以当你修改_fruits的元素时,实际操作的是同一个列表对象,widget.fruits自然也会同步变化。

解决方案

初始化本地列表时,创建原列表的副本,让_fruits指向一个新的列表对象即可。修改initState中的赋值代码:

方式1:使用List.from

_fruits = List.from(widget.fruits);

方式2:使用扩展运算符

_fruits = [...widget.fruits];

这样后续对_fruits的修改只会影响这个新的列表副本,不会改变原有的widget.fruits。

内容的提问来源于stack exchange,提问作者Rishi Laishram

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 09:54:22