Flutter Flip Widget重建时的值持久化问题
解决Flip Widget重建时保留异步变量值的问题
核心思路
不要将cPrayerTime、remingTime、cPrayerName定义在组件的build方法内(否则每次重建都会重置为空),而是把它们存储在State类成员变量或全局状态管理容器中,确保异步赋值后的值在组件重建时得以保留。
方案1:使用StatefulWidget的状态存储
这是最基础的解决方式,适合单个组件内的状态保留:
class PrayerFlipCard extends StatefulWidget { const PrayerFlipCard({super.key}); @override State<PrayerFlipCard> createState() => _PrayerFlipCardState(); } class _PrayerFlipCardState extends State<PrayerFlipCard> { // 将变量作为State类的成员,重建时不会重置 String? cPrayerTime; String? remingTime; String? cPrayerName; @override void initState() { super.initState(); // 组件初始化时调用异步函数获取数据 _loadPrayerData(); } // 模拟异步获取数据的函数 Future<void> _loadPrayerData() async { // 替换成你的实际异步请求逻辑 final fetchedData = await Future.delayed( const Duration(seconds: 1), () => { 'prayerTime': '18:30', 'remainingTime': '25分钟', 'prayerName': 'Maghrib' }, ); // 更新状态,触发UI重建 setState(() { cPrayerTime = fetchedData['prayerTime']; remingTime = fetchedData['remainingTime']; cPrayerName = fetchedData['prayerName']; }); } @override Widget build(BuildContext context) { return FlipWidget( // 正面卡片使用已获取的变量值 front: _buildFrontCard(), // 背面卡片同样复用变量值 back: _buildBackCard(), // 翻转时可选择是否重新获取数据,不调用则保留现有值 onFlipCompleted: () { // _loadPrayerData(); // 不需要刷新就注释掉 }, ); } Widget _buildFrontCard() { return Card( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(cPrayerName ?? '加载中...', style: const TextStyle(fontSize: 20)), const SizedBox(height: 10), Text(cPrayerTime ?? '--:--', style: const TextStyle(fontSize: 30)), const SizedBox(height: 10), Text('剩余时间: ${remingTime ?? '--'}'), ], ), ), ); } Widget _buildBackCard() { return Card( child: Center( child: Text( '${cPrayerName ?? '未知'} 祈祷提示', style: const TextStyle(fontSize: 22), ), ), ); } }
方案2:使用状态管理工具(跨组件共享)
如果需要在多个组件间共享这些变量,或者组件层级较深,可使用Riverpod、Provider等状态管理库,将数据提升到全局状态:
// 1. 定义数据模型 class PrayerData { final String prayerTime; final String remainingTime; final String prayerName; PrayerData({ required this.prayerTime, required this.remainingTime, required this.prayerName, }); } // 2. 定义全局状态提供者 final prayerDataProvider = StateProvider<PrayerData?>((ref) => null); // 3. 在组件中使用状态 class PrayerFlipCard extends ConsumerWidget { const PrayerFlipCard({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final prayerData = ref.watch(prayerDataProvider); // 首次加载时获取数据 if (prayerData == null) { _loadPrayerData(ref); } return FlipWidget( front: _buildFrontCard(prayerData), back: _buildBackCard(prayerData), ); } Future<void> _loadPrayerData(WidgetRef ref) async { final fetchedData = await Future.delayed( const Duration(seconds: 1), () => PrayerData( prayerTime: '18:30', remainingTime: '25分钟', prayerName: 'Maghrib', ), ); // 更新全局状态 ref.read(prayerDataProvider.notifier).state = fetchedData; } Widget _buildFrontCard(PrayerData? data) { return Card( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(data?.prayerName ?? '加载中...', style: const TextStyle(fontSize: 20)), const SizedBox(height: 10), Text(data?.prayerTime ?? '--:--', style: const TextStyle(fontSize: 30)), const SizedBox(height: 10), Text('剩余时间: ${data?.remainingTime ?? '--'}'), ], ), ), ); } Widget _buildBackCard(PrayerData? data) { return Card( child: Center( child: Text( '${data?.prayerName ?? '未知'} 祈祷提示', style: const TextStyle(fontSize: 22), ), ), ); } }
关键注意点
- 避免在
build方法内定义变量,因为build会在组件重建时反复执行,变量会被重新初始化。 - 异步赋值后必须调用
setState(StatefulWidget)或更新状态管理的状态,才能触发UI刷新显示最新值。 - 如果不需要每次翻转都刷新数据,不要在翻转回调中重新调用异步函数,这样就能保留第一次加载的值。
内容的提问来源于stack exchange,提问作者Afthal Ad
相关产品推荐
相关产品推荐

