Dart 正在重建的颤振集团
我正在探索颤振和团块模式,为了练习,我正在制作一个关于比萨饼的应用程序 我正在使用Dart 正在重建的颤振集团,dart,flutter,bloc,Dart,Flutter,Bloc,我正在探索颤振和团块模式,为了练习,我正在制作一个关于比萨饼的应用程序 我正在使用BlocProvider访问块。这是包装上的。它是一个基本的实现,使用InheritedWidget与无状态widget相结合 我有一个带有两个可编辑文本字段的页面,用于我想要创建的比萨饼的名称和价格。它由一个集团支持 代码如下: AddPizzaPage.dart: class AddPizzaPage extends StatelessWidget { @override Widget build(Bu
BlocProvider
访问块。这是包装上的。它是一个基本的实现,使用InheritedWidget
与无状态widget
相结合
我有一个带有两个可编辑文本字段的页面,用于我想要创建的比萨饼的名称和价格。它由一个集团支持
代码如下:
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(),
),
);
}
}
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();
},
)
],
),
);
}
}
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);
}
}
}
列表页。省道:
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(),
),
);
}
}
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();
},
)
],
),
);
}
}
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);
}
}
}
class ModifyPizzaWidget扩展了无状态widget{
@凌驾
小部件构建(构建上下文){
最终添加pizzabloc=BlocProvider.of
我不知道如何使用bloc为addPizza表单供电。发生这种情况是因为您正在使用build方法创建bloc的实例:
BlocProvider(
bloc: Bloc(),
child: ...
)
其结果是,任何重建都不会重用以前的实例(也有一些可怕的内存泄漏)
解决方案是创建一个StatefulWidget
,并在initState
中创建该BLoC实例,然后执行dispose
覆盖以清理内容
但是既然你已经在使用一个软件包,你可以用它来代替。它是一个流行的替代品,可以完成上面列出的所有事情
因此,您的BlocProvider
使用变得:
StatefulProvider(
valueBuilder: (_) => AddPizzaBloc(),
dispose: (_, bloc) => bloc.dispose(),
child: // ...
),
然后获得如下结果:
Provider.of<AddPizzaBloc>(context);
Provider.of(上下文);
我同意,为了完成回答,即使AddPizzaPage是一个无状态小部件,颤振框架也会在虚拟键盘在屏幕上显示和隐藏时重建此小部件。如果您不想使用Statefull小部件,其他选项(但不是最好的)是在类构造函数中创建bloc things,但您将无法关闭流s不再需要时导致泄漏。我发誓我本周查找了提供程序包,当时没有StatefulProvider!感谢您的帮助。@Yutsa您需要使用提供程序而不是StatefulProvider,因为它们合并在一起了