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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 21:20:33