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

Flutter页面切换后计算状态丢失问题求助(已用KeepAlive)

问题分析与解决方案

核心问题

AutomaticKeepAliveClientMixin 仅适用于 TabBarView/PageView 这类页面切换场景下的状态保持,对Navigator跳转(push/pop)的场景无效。你遇到的计算结果重置问题,本质是页面状态未被正确持久化,或返回逻辑导致页面重建。

修复步骤

1. 修正Add按钮的计算逻辑(避免累加错误)

当前代码每次点击Add是在原有结果上累加所有输入值,这不是正确的“计算总和”逻辑,应改为每次重新计算输入框的总和:

onPressed: () {
  setState(() {
    // 先重置结果,再重新计算总和
    roundOneResult = 0;
    roundTwoResult = 0;
    roundOneFields.forEach((e) =>
        roundOneResult += int.parse(e.text));
    roundTwoFields.forEach((e) =>
        roundTwoResult += int.parse(e.text));
  });
},

2. 确保返回逻辑正确(避免创建新页面)

检查Navbar页面的返回按钮,必须使用Navigator.pop(context)回到原页面,而不是重新push一个新的AddTwoNumbers实例:

// Navbar页面中的返回按钮示例
IconButton(
  icon: Icon(Icons.arrow_back),
  onPressed: () => Navigator.pop(context),
)

3. 持久化计算结果(防止页面被系统回收)

如果页面因系统内存不足被回收,可使用PageStorage保存结果变量:

  • 在State类中定义PageStorageKey:
    final PageStorageKey _storageKey = PageStorageKey('add_two_numbers_state');
    
  • 在Scaffold中设置key:
    return Scaffold(
      key: _storageKey,
      // ...其他代码
    );
    
  • 使用PageStorage.of(context)保存/读取结果:
    @override
    void initState() {
      super.initState();
      roundOneFields = List.generate(20, (index) => TextEditingController(text: '0'));
      roundTwoFields = List.generate(20, (index) => TextEditingController(text: '0'));
      // 从PageStorage读取保存的结果
      roundOneResult = PageStorage.of(context)?.readState(context, identifier: 'roundOneResult') ?? 0;
      roundTwoResult = PageStorage.of(context)?.readState(context, identifier: 'roundTwoResult') ?? 0;
    }
    
    @override
    void didUpdateWidget(covariant AddTwoNumbers oldWidget) {
      super.didUpdateWidget(oldWidget);
      // 保存结果到PageStorage
      PageStorage.of(context)?.writeState(context, roundOneResult, identifier: 'roundOneResult');
      PageStorage.of(context)?.writeState(context, roundTwoResult, identifier: 'roundTwoResult');
    }
    

4. 进阶方案:使用状态管理库

如果需要更可靠的全局状态管理,可使用Provider、GetX等库,将计算结果存储在全局状态中,避免页面重建导致的状态丢失。

最终代码示例(整合修复)

import 'package:flutter/material.dart';
import 'package:tca/navbar.dart';

void main() {
  runApp(const MaterialApp(home: AddTwoNumbers()));
}

class AddTwoNumbers extends StatefulWidget {
  const AddTwoNumbers({super.key});

  @override
  State<AddTwoNumbers> createState() => _AddTwoNumbersState();
}

class _AddTwoNumbersState extends State<AddTwoNumbers> {
  final PageStorageKey _storageKey = PageStorageKey('add_two_numbers_state');
  List<TextEditingController> roundOneFields = [];
  List<TextEditingController> roundTwoFields = [];
  int roundOneResult = 0;
  int roundTwoResult = 0;

  @override
  void initState() {
    super.initState();
    roundOneFields = List.generate(20, (index) => TextEditingController(text: '0'));
    roundTwoFields = List.generate(20, (index) => TextEditingController(text: '0'));
    // 读取保存的状态
    final storage = PageStorage.of(context);
    roundOneResult = storage?.readState(context, identifier: 'roundOneResult') ?? 0;
    roundTwoResult = storage?.readState(context, identifier: 'roundTwoResult') ?? 0;
  }

  @override
  void didUpdateWidget(covariant AddTwoNumbers oldWidget) {
    super.didUpdateWidget(oldWidget);
    // 保存状态
    final storage = PageStorage.of(context);
    storage?.writeState(context, roundOneResult, identifier: 'roundOneResult');
    storage?.writeState(context, roundTwoResult, identifier: 'roundTwoResult');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _storageKey,
      appBar: AppBar(
        title: const Text('Twin City Bowmen Score Sheet'),
        actions: <Widget>[
          IconButton(
            icon: const Icon(Icons.notifications),
            onPressed: () {},
          )
        ],
        backgroundColor: Colors.orangeAccent,
        leading: IconButton(
          icon: const Icon(Icons.menu),
          onPressed: () {},
        ),
        shape: const RoundedRectangleBorder(
            borderRadius: BorderRadius.only(
                bottomLeft: Radius.circular(25),
                bottomRight: Radius.circular(25))),
      ),
      body: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            Row(
              children: [
                Expanded(
                  child: ListView.builder(
                    itemCount: 20,
                    shrinkWrap: true,
                    itemBuilder: (context, index) => Row(
                      children: <Widget>[
                        Text("R1 Target ${index + 1}:"),
                        Flexible(
                          child: TextField(
                            decoration: const InputDecoration(
                                contentPadding:
                                    EdgeInsets.symmetric(horizontal: 8)),
                            keyboardType: TextInputType.number,
                            controller: roundOneFields[index],
                          ),
                        ),
                      ],
                    ),
                    physics: const BouncingScrollPhysics(),
                  ),
                ),
                const SizedBox(width: 24),
                Expanded(
                  child: ListView.builder(
                    itemCount: 20,
                    shrinkWrap: true,
                    physics: const BouncingScrollPhysics(),
                    itemBuilder: (context, index) => Row(
                      children: <Widget>[
                        Text("R2 Target ${index + 1}:"),
                        Flexible(
                          child: TextField(
                            decoration: const InputDecoration(
                                contentPadding:
                                    EdgeInsets.symmetric(horizontal: 8)),
                            keyboardType: TextInputType.number,
                            controller: roundTwoFields[index],
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                ElevatedButton(
                  child: const Text("Add"),
                  onPressed: () {
                    setState(() {
                      // 重置后重新计算总和
                      roundOneResult = 0;
                      roundTwoResult = 0;
                      roundOneFields.forEach((e) =>
                          roundOneResult += int.parse(e.text));
                      roundTwoFields.forEach((e) =>
                          roundTwoResult += int.parse(e.text));
                    });
                  },
                )
              ],
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                ElevatedButton(
                    child: const Text("Go to Navbar"),
                    onPressed: () => Navigator.push(context,
                        MaterialPageRoute(builder: (context) => const Navbar())))
              ],
            ),
            Text(
              "Result \n Round 1: $roundOneResult and Round 2: $roundTwoResult Total = ${roundOneResult + roundTwoResult}",
              textAlign: TextAlign.center,
              style: const TextStyle(fontSize: 30),
            ),
          ],
        ),
      ),
    );
  }
}

内容的提问来源于stack exchange,提问作者securityNVR NVR

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 21:40:56