Flutter使用动态数据构建页面时setState不刷新Widget树问题
问题原因
- 你将
data的赋值逻辑直接写在了build方法内部,每次调用setState()触发页面重绘时,build方法都会重新执行,你修改后的data值会被硬编码的初始值直接覆盖,所以看起来界面没有发生更新。
解决方案
把data的初始化逻辑从build方法移出去:如果是初始默认值可以放到initState生命周期中;如果是需要根据业务条件(比如用户切换公式)动态更新data列表,把赋值逻辑放到对应的业务触发回调中执行,不要在build里直接赋值,避免重绘时被覆盖。
修改后的可运行代码示例
import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const DynamicWidget(), ); } } class DynamicWidget extends StatefulWidget { const DynamicWidget({Key? key}) : super(key: key); @override _DynamicWidgetState createState() => _DynamicWidgetState(); } class _DynamicWidgetState extends State<DynamicWidget> { List<Map<String, String>> data = []; @override void initState() { super.initState(); // 把data的初始化逻辑移到initState,不要放在build里 data = [ {"name": 'c', "unit": "cm"} ]; } @override Widget build(BuildContext context) { // 此处不要直接给data赋值,避免重绘时覆盖修改后的值 // 如果你的data需要根据其他业务条件动态变更,把赋值逻辑放到对应的业务回调中,调用setState更新即可 return Scaffold( appBar: AppBar( elevation: 0, title: const Text('示例'), ), body: Column( children: [ Text(data.toString()), ListView.builder( itemCount: data.length, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemBuilder: (_, int i) { return Row( children: [ Text("Unit for ${data[i]['name']} :"), const SizedBox(width: 10), DropdownButton( elevation: 0, value: data[i]['unit'], onChanged: (String? newUnit) { setState(() { data[i]['unit'] = newUnit!; print("data = $data"); }); }, underline: Container(height: 2, color: Colors.cyan), items: ["km", "hm", "dam", "m", "dm", "cm", "mm"] .map<DropdownMenuItem<String>>( (String value) { return DropdownMenuItem<String>( value: value, child: Text(value), ); }, ).toList(), ), ], ); }, ), ], ), ); } }
内容的提问来源于stack exchange,提问作者ThomasG2201
相关产品推荐
相关产品推荐

