按下背面的 TextEditingController 时出现问题

问题描述 投票:0回答:1

我的 Flutter 应用程序中有以下

StatefulWidget

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

  @override
  State<EditProfilePage> createState() => _EditProfilePageState();
}

class _EditProfilePageState extends State<EditProfilePage> {
  ProfileClient client = ProfileClient();
  TextEditingController usernameController = TextEditingController();
  Future<ProfileResponse>? futureProfileResponse;

  @override
  void initState() {
    super.initState();
    futureProfileResponse = fetch();
  }

  Future<ProfileResponse> fetch() async {
    String key = await Utils.getKey();
    return client.get(key);
  }

  @override
  void dispose() {
    usernameController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('Edit profile'),
        ),
        body: SingleChildScrollView(
            child: ConstrainedBox(
                constraints: BoxConstraints(
                    maxHeight: MediaQuery.of(context).size.height),
                child: buildPage())));
  }

  FutureBuilder<ProfileResponse> buildPage() {
    return FutureBuilder<ProfileResponse>(
        future: futureProfileResponse,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            ProfileResponse profileResponse = snapshot.data!;
            if (profileResponse.code == 200) {
              usernameController.text = profileResponse.profile.username;
              return Padding(
                padding: const EdgeInsets.all(24),
                child: Column(
                  children: [
                    TextField(
                      controller: usernameController,
                      decoration: const InputDecoration(
                        labelText: 'Username',
                      ),
                    ),
                  ],
                ),
              );
            }
          }
          return const Center(child: CircularProgressIndicator());
        });
  }
}

我不明白为什么,在用户名里面写

TextField
,然后按后退按钮,
TextField
的内容又回到之前的值。

这是一个演示,可以更好地理解我的问题: Demo GIF

准确地说,当我用

buildPage()
小部件包装
ConstrainedBox
方法时,这个问题就开始出现。我这样做是因为在我的原始页面中我有更多
TextField
小部件,我需要它们在打开键盘时“向上移动”。为了简单起见,我删除了与这个特定问题无关的部分代码。

flutter textfield onbackpressed texteditingcontroller constrainedbox
1个回答
0
投票

当用户打开/关闭键盘时,可用的屏幕尺寸将发生变化,这使得小部件重建。整个

FutureBuilder
将被重建,并且
builder
将执行将文本分配给控制器的行。您可以通过在其前面添加打印语句来验证:

print('Widget rebuild at ${DateTime.now()}');
usernameController.text = profileResponse.profile.username;

使用

FutureBuilder
的原因是仅在 future 完成后渲染
TextField
,否则渲染
CircularProgressIndicator
。设置控制器的值应该与这个小部件构建机制分开。您可以在
text
方法中设置控制器的
fetch
值:

Future<ProfileResponse> fetch() async {
  String key = await Utils.getKey();
  final profileResponse = client.get(key);
  usernameController.text = profileResponse.profile.username;
  return profileResponse;
}

FutureBuilder
中,删除此行:

usernameController.text = profileResponse.profile.username;

这样,当小部件重建时,

usernameController.text
赋值线就不会被调用。

© www.soinside.com 2019 - 2024. All rights reserved.