Flutter Bloc 不会更改 TextFormField 初始值

lok*_*oki 11 flutter bloc flutter-bloc

我正在使用 Bloc 库,并注意到在产生新状态后我的TextFormField初始值没有改变。

我的应用程序比这更复杂,但我做了一个最小的例子。还跟踪推送事件后状态的变化。

Bloc 应该正确重建整个小部件。我错过了什么吗?

import 'package:flutter/material.dart';
import 'package:bloc/bloc.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'dart:developer' as developer;

void main() {
  runApp(MyApp());
}

enum Event { first }

class ExampleBloc extends Bloc<Event, int> {
  ExampleBloc() : super(0);
  @override
  Stream<int> mapEventToState(Event event) async* {
    yield state + 1;
  }
}

class MyApp extends StatelessWidget {
  const MyApp({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BlocProvider(
        create: (_) => ExampleBloc(),
        child: Builder(
          builder: (contex) => SafeArea(
            child: BlocConsumer<ExampleBloc, int>(
                listener: (context, state) {},
                builder: (context, int state) {
                  developer.log(state.toString());
                  return Scaffold(
                    body: Form(
                      child: Column(
                        children: [
                          TextFormField(
                            autocorrect: false,
                            initialValue: state.toString(),
                          ),
                          RaisedButton(
                            child: Text('Press'),
                            onPressed: () {
                              context.bloc<ExampleBloc>().add(Event.first);
                            },
                          )
                        ],
                      ),
                    ),
                  );
                }),
          ),
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

pubspec.yaml

name: form
description: A new Flutter project.
version: 1.0.0+1
environment:
  sdk: ">=2.7.0 <3.0.0"
dependencies:
  flutter:
    sdk: flutter
  bloc: ^6.0.0
  flutter_bloc: ^6.0.0
Run Code Online (Sandbox Code Playgroud)

编辑
@chunhunghan 指出添加 UniqueKey 可以解决此问题。我还应该提到我的情况。onChanged该应用程序通过两个方法发出事件TextFormField。这会导致表单重置并删除键盘。自动对焦不起作用,因为有两个TextFormFieldwgich 发出事件。

chu*_*han 6

您可以复制粘贴运行下面的完整代码 1 和 2
\n您可以提供UniqueKey()Scaffold强制TextFormField重新创建
\n您可以参考https://medium.com/flutter/keys-what-are-they-good-for-13cb51742e7d了解详细信息

\n

如果 Element 的 key 与相应 Widget 的 key 不匹配。这会导致 Flutter 停用这些元素并删除对元素树中元素的引用

\n

解决方案一:

\n
return Scaffold(\n        key: UniqueKey(),\n        body: Form(\n
Run Code Online (Sandbox Code Playgroud)\n

解决方案2:

\n
TextFormField(\n               key: UniqueKey(),\n
Run Code Online (Sandbox Code Playgroud)\n

工作演示

\n

在此输入图像描述

\n

完整代码 1ScaffoldUniqueKey

\n
import \'package:flutter/material.dart\';\nimport \'package:bloc/bloc.dart\';\nimport \'package:flutter_bloc/flutter_bloc.dart\';\nimport \'dart:developer\' as developer;\n\nvoid main() {\n  runApp(MyApp());\n}\n\nenum Event { first }\n\nclass ExampleBloc extends Bloc<Event, int> {\n  ExampleBloc() : super(0);\n  @override\n  Stream<int> mapEventToState(Event event) async* {\n    yield state + 1;\n  }\n}\n\nclass MyApp extends StatelessWidget {\n  const MyApp({Key key}) : super(key: key);\n\n  @override\n  Widget build(BuildContext context) {\n    print("build");\n    return MaterialApp(\n      home: BlocProvider(\n        create: (_) => ExampleBloc(),\n        child: Builder(\n          builder: (contex) => SafeArea(\n            child: BlocConsumer<ExampleBloc, int>(\n                listener: (context, state) {},\n                builder: (context, int state) {\n                  print("state ${state.toString()}");\n                  developer.log(state.toString());\n                  return Scaffold(\n                    key: UniqueKey(),\n                    body: Form(\n                      child: Column(\n                        children: [\n                          TextFormField(\n                            autocorrect: false,\n                            initialValue: state.toString(),\n                          ),\n                          RaisedButton(\n                            child: Text(\'Press\'),\n                            onPressed: () {\n                              context.bloc<ExampleBloc>().add(Event.first);\n                            },\n                          )\n                        ],\n                      ),\n                    ),\n                  );\n                }),\n          ),\n        ),\n      ),\n    );\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

完整代码TextFormField2UniqueKey

\n
import \'package:flutter/material.dart\';\nimport \'package:bloc/bloc.dart\';\nimport \'package:flutter_bloc/flutter_bloc.dart\';\nimport \'dart:developer\' as developer;\n\nvoid main() {\n  runApp(MyApp());\n}\n\nenum Event { first }\n\nclass ExampleBloc extends Bloc<Event, int> {\n  ExampleBloc() : super(0);\n  @override\n  Stream<int> mapEventToState(Event event) async* {\n    yield state + 1;\n  }\n}\n\nclass MyApp extends StatelessWidget {\n  const MyApp({Key key}) : super(key: key);\n\n  @override\n  Widget build(BuildContext context) {\n    print("build");\n    return MaterialApp(\n      home: BlocProvider(\n        create: (_) => ExampleBloc(),\n        child: Builder(\n          builder: (contex) => SafeArea(\n            child: BlocConsumer<ExampleBloc, int>(\n                listener: (context, state) {},\n                builder: (context, int state) {\n                  print("state ${state.toString()}");\n                  developer.log(state.toString());\n                  return Scaffold(\n                    body: Form(\n                      child: Column(\n                        children: [\n                          TextFormField(\n                            key: UniqueKey(),\n                            autocorrect: false,\n                            initialValue: state.toString(),\n                          ),\n                          RaisedButton(\n                            child: Text(\'Press\'),\n                            onPressed: () {\n                              context.bloc<ExampleBloc>().add(Event.first);\n                            },\n                          )\n                        ],\n                      ),\n                    ),\n                  );\n                }),\n          ),\n        ),\n      ),\n    );\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n