【问题标题】:Flutter BLoC being recreated正在重新创建 Flutter BLoC
【发布时间】:2019-06-28 15:44:20
【问题描述】:

我正在发现 Flutter 和 bloc 模式,并且为了练习我正在制作一个关于披萨的应用。

我正在使用BlocProvider 来访问这些块。它来自generic_bloc_provider 包。它是使用InheritedWidget 结合StatelessWidget 的基本实现。

我有一个包含两个可编辑文本字段的页面,用于显示我想要创建的披萨的名称和价格。它由一个集团支持。

代码如下:

AddPizzaPage.dart :

class AddPizzaPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("Building AddPizzaPage");
    return Scaffold(
      appBar: AppBar(
        title: Text("Adding Pizza"),
      ),
      body: BlocProvider(
        bloc: AddPizzaBloc(),
        child: ModifyPizzaWidget(),
      ),
    );
  }
}

ListPage.dart:

class ModifyPizzaWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final addPizzaBloc = BlocProvider.of<AddPizzaBloc>(context);
    return Container(
      margin: EdgeInsets.all(16.0),
      child: Column(
        children: <Widget>[
          TextField(
            decoration: InputDecoration(hintText: "Nom de la pizza"),
            onChanged: (name) {
              addPizzaBloc.pizzaNameSink.add(name);
            },
          ),
          TextField(
            decoration: InputDecoration(hintText: "Prix de la pizza"),
            keyboardType: TextInputType.number,
            onChanged: (price) {
              addPizzaBloc.pizzaPriceSink.add(price);
            },
          ),
          IconButton(
            icon: Icon(Icons.check),
            iconSize: 40,
            onPressed: () {
              addPizzaBloc.evenSink.add(AddPizzaEvent.VALIDATE);
              Navigator.of(context).pop();
            },
          )
        ],
      ),
    );
  }
}

AddPizzaBloc.dart:

enum AddPizzaEvent {
  VALIDATE
}

class AddPizzaBloc extends Bloc {
  final _pizza = Pizza.empty();
  final _pizzaSubject = BehaviorSubject<Pizza>();
  final _repository = PizzaRepository();

  Sink<String> get pizzaNameSink => _pizzaNameController.sink;
  final _pizzaNameController = StreamController<String>();

  Sink<String> get pizzaPriceSink => _pizzaPriceController.sink;
  final _pizzaPriceController = StreamController<String>();

  Sink<AddPizzaEvent> get evenSink => _eventSink.sink;
  final _eventSink = StreamController<AddPizzaEvent>();

  AddPizzaBloc() {
    print("Created");
    _pizzaNameController.stream.listen(_addPizzaName);
    _pizzaPriceController.stream.listen(_addPizzaPrice);
    _eventSink.stream.listen(_onEventReceived);
  }

  dispose() {
    print("Disposed");
    _pizzaSubject.close();
    _pizzaNameController.close();
    _pizzaPriceController.close();
    _eventSink.close();
  }

  void _addPizzaName(String pizzaName) {
    _pizza.name = pizzaName;
    print(_pizza);
  }

  void _addPizzaPrice(String price) {
    var pizzaPrice = double.tryParse(price) ?? 0.0;
    _pizza.price = pizzaPrice;
    print(_pizza);
  }

  void _onEventReceived(AddPizzaEvent event) {
    print("Received $event");
    if (event == AddPizzaEvent.VALIDATE) {
      print(_pizza);
      _repository.addPizza(_pizza);
    }
  }
}

我的问题是我将正在构建的 Pizza 存储在块内,但小部件被重建,因此块被重建并且我失去了状态。

完整代码可在gitlab获取

我不知道如何使用 bloc 来驱动 addPizza 表单。

【问题讨论】:

    标签: dart flutter bloc


    【解决方案1】:

    这是因为您在 build 方法中创建 BLoC 的实例:

    BlocProvider(
      bloc: Bloc(),
      child: ...
    )
    

    结果是任何重建都不会重用以前的实例(也有一些可怕的内存泄漏)。

    解决方案是创建一个 StatefulWidget 并在 initState 中创建该 BLoC 实例,然后覆盖 dispose 以清理内容。

    但由于您已经在使用包,您可以改用provider。它是一种流行的替代方案,可以完成上面列出的所有操作。

    因此,您的BlocProvider 用法变为:

    StatefulProvider(
       valueBuilder: (_) =>  AddPizzaBloc(),
       dispose: (_, bloc) => bloc.dispose(),
       child: // ...
    ),
    

    然后这样获得:

    Provider.of<AddPizzaBloc>(context);
    

    【讨论】:

    • 我同意并且只是为了完成答案,即使 AddPizzaPage 是一个无状态小部件颤振框架,当虚拟键盘显示并隐藏在您的屏幕上时,它也会重建此小部件。如果您不想使用 Statefull 小部件,其他选项但不是最好的选择是在类构造函数中创建您的 bloc 事物,但是当不再需要导致泄漏时您将无法关闭流。
    • 我发誓我这周查看了提供程序包,当时没有 StatefulProvider !感谢您的帮助。
    • @Yutsa 你需要使用 Provider 而不是 StatefulProvider 因为它们被合并在一起了
    猜你喜欢
    • 2021-03-19
    • 2020-06-17
    • 2019-12-26
    • 2021-08-28
    • 2020-04-28
    • 2020-10-10
    • 2021-03-22
    • 2021-01-19
    • 1970-01-01
    相关资源
    最近更新 更多