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

Flutter:如何让TextFormField初始值同步SharedPreferences存储的计数器?

问题分析与解决方案

没关系,新手遇到这种异步加载的问题太正常了,咱们来一步步拆解问题~

你的核心需求是让TextFormField的初始值和存在SharedPreferences里的counter保持一致,但现在重启后文本框显示0,问题出在这两点:

  1. _loadCounter是异步方法(用到了await),App启动时第一次执行build方法的时候,_counter还是初始的0;
  2. TextFormField的initialValue只会在Widget第一次初始化时生效,哪怕之后_counter通过setState更新了,输入框也不会自动同步这个值。

下面给你两种实用的解决方案,你可以根据需求选:


方案一:使用TextEditingController(推荐,更灵活)

TextEditingController是Flutter专门用来控制输入框内容的工具,能随时动态更新输入框的文本,非常适合你的场景。

修改代码的步骤:

  1. 定义一个TextEditingController变量;
  2. 在initState里初始化它,等SharedPreferences加载完counter后,更新controller的文本;
  3. 点击递增按钮时,同时更新_counter和controller的文本;
  4. 记得在页面销毁时释放controller,避免内存泄漏。

修改后的完整代码:

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Shared preferences demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Shared preferences demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  // 1. 定义TextEditingController
  TextEditingController _textController;

  @override
  void initState() {
    super.initState();
    // 2. 初始化controller
    _textController = TextEditingController();
    _loadCounter();
  }

  _loadCounter() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    setState(() {
      _counter = (prefs.getInt('counter') ?? 0);
      // 加载完成后更新输入框内容
      _textController.text = '$_counter';
    });
  }

  _incrementCounter() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    setState(() {
      _counter = (prefs.getInt('counter') ?? 0) + 1;
      prefs.setInt('counter', _counter);
      // 点击递增时同步更新输入框
      _textController.text = '$_counter';
    });
  }

  @override
  void dispose() {
    // 3. 页面销毁时释放controller
    _textController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
            // 4. 把initialValue换成controller
            TextFormField(
              controller: _textController,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

方案二:用FutureBuilder等待加载完成

如果你不想用Controller,可以用FutureBuilder包裹TextFormField,等_loadCounter执行完成后再渲染输入框,这样初始值就会直接是保存的counter值。

修改build方法里的TextFormField部分即可:

// 替换原来的TextFormField
FutureBuilder(
  future: _loadCounter(), // 等待加载完成
  builder: (context, snapshot) {
    // 加载完成后再显示输入框
    if (snapshot.connectionState == ConnectionState.done) {
      return TextFormField(
        initialValue: '$_counter',
      );
    }
    // 加载中可以显示一个加载提示
    return CircularProgressIndicator();
  },
)

注意:这种方式下,点击递增按钮后,_counter更新会触发setState,FutureBuilder会重新执行_loadCounter,不过因为SharedPreferences是本地存储,性能影响很小,也能正常工作。


新手小提示

  • 异步操作(比如await SharedPreferences.getInstance())不会阻塞UI,但会延后执行,所以要注意变量更新的时机;
  • 用TextEditingController不仅能控制初始值,还能随时读取或修改输入框的内容,后续如果需要让输入框和其他组件联动,会非常方便;
  • 所有的Controller在页面销毁时都要记得调用dispose(),避免内存泄漏哦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 20:28:10