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

为什么Flutter中TextFormField获得焦点时页面会自动重载?

问题根本原因

你当前将Users.doc(uid).get()这个Future直接写在了FutureBuilder的future属性中,每次调用setState触发页面重绘时,都会重新执行这个Future请求,导致FutureBuilder刷新重建,输入框的状态被重置,自然无法正常输入。你查到的把Future放到initState中预加载的思路是完全正确的。

具体实现步骤

  1. 在State类中定义一个Future类型的变量,用来缓存用户数据请求:
class _UpdateProfileState extends State<UpdateProfile> {
  final GlobalKey<FormState> _formKey  = GlobalKey<FormState>();
  // 新增缓存请求的变量
  late Future<DocumentSnapshot> _userFuture;
  late String _name;
  // 其余原有变量保留
}
  1. 在initState生命周期方法中初始化这个Future,该方法只会在组件初始化时执行一次,不会跟随页面重绘重复触发:
@override
void initState() {
  super.initState();
  _userFuture = Users.doc(uid).get();
}
  1. 将FutureBuilder的future参数替换为缓存好的_userFuture变量,同时在拿到数据时给_name赋初始值:
FutureBuilder<DocumentSnapshot>(
  // 替换为缓存的请求变量,不要直接写请求方法
  future: _userFuture,
  builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
    if (snapshot.hasError) {
      return Text("Something went wrong");
    }
    if (snapshot.hasData && !snapshot.data!.exists) {
      return Text("Document does not exist");
    }
    if (snapshot.connectionState == ConnectionState.done) {
      // 给_name赋初始值
      Map<String, dynamic> data = snapshot.data!.data() as Map<String, dynamic>;
      _name = data['displayName'].toString();
      return displayUserInformation(context, snapshot);
    } else {
      return SizedBox(height: 400,
          child: Center(child: CircularProgressIndicator()));
    }
  },
),
  1. 调整TextFormField的initialValue取值,直接取_name即可:
TextFormField(
  onChanged: (value) => setState(() => _name = value.trim()),
  initialValue: _name,
  // 其余原有配置保持不变
  cursorColor: DarkTurquoise,
  decoration: InputDecoration(
    labelText: 'Name',
    labelStyle: TextStyle(
        color: SeaTurquoise
    ),
    focusedBorder: UnderlineInputBorder(
      borderSide:  BorderSide(color: SeaTurquoise, width: 2.0),),
    enabledBorder: UnderlineInputBorder(
      borderSide: BorderSide(color: DarkGrey),
    ),
  ),
)

补充注意点

如果后续需要更灵活地控制输入内容,可以选择使用TextEditingController替代initialValue的写法,同样在initState中给控制器赋初始值即可,两种方案都可以解决输入重置的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 01:36:04