#flutter #bloc #stream-builder
#flutter #блок #stream-builder
Вопрос:
Я пытаюсь использовать блочную архитектуру в приложении Flutter, и для этой цели я использую StreamController и StreamBuilder. Проблема в том, что StreamBuilder повторяет последний снимок.данные каждый раз, когда они возвращаются. Я вкладываю StreamBuilders. Итак, есть один основной StreamBuilder. Его поток определен в файле mainBloc. initialData — это SomeEvent, а someView возвращается.
someView — это другой StreamBuilder с соответствующим блоком и потоком. initialData — это InitialEvent . При нажатии кнопки SecondEvent добавляется в приемник блоков, и поэтому виджет изменяется. В новом представлении есть еще одна кнопка, и при нажатии на нее mainBloc должен снова показать тот же someView.
Проблема здесь. someView StreamBuilder получает снимок.данные, которые совпадают с последними, но последние не добавляются в приемник снова. Итак, я не понимаю — это то, как должен работать StreamBuilder? Чего я хотел бы добиться, так это этого снимка.вместо этого данные имеют InitialEvent . Возможно ли это? Или, по крайней мере, чтобы не иметь моментального снимка.данные повторяются без запуска.
Приведенный ниже код демонстрирует всю проблему.
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
MainBloc mainBloc;
Bloc bloc;
MyApp() {
mainBloc = MainBloc();
bloc = Bloc();
}
Widget mainView() {
return StreamBuilder<MainEvent>(
stream: mainBloc.mainStream,
initialData: SomeEvent(),
builder: (
context,
snapshot,
) {
if (snapshot.hasData) {
MainEvent event = snapshot.data;
if (event is SomeEvent) {
return someView();
}
if (event is SomeEventTwo) {
return someView();
}
} else {
return Container(height: 0, width: 0);
}
},
);
}
Widget someView() {
return StreamBuilder<Event>(
stream: bloc.stream,
initialData: InitialEvent(),
builder: (
context,
snapshot,
) {
if (snapshot.hasData) {
Event event = snapshot.data;
if (event is InitialEvent) {
return Column(
children: [
Center(
child: Text("Initial event"),
),
FlatButton(
onPressed: () {
bloc.secondEvent();
},
child: Text("Trigger Second event"),
color: Colors.pink,
),
],
);
}
if (event is SecondEvent) {
return Center(
child: FlatButton(
child: Text("Show same screen again"),
onPressed: () {
bloc.dispose();
bloc = Bloc();
mainBloc.showScreenTwo();
},
color: Colors.blue,
),
);
}
} else {
return Container(height: 0, width: 0);
}
},
);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
backgroundColor: Colors.grey,
),
body: mainView(),
),
);
}
}
Это блоки:
MainBloc:
class MainBloc {
StreamController<MainEvent> _mainStreamController;
StreamSink<MainEvent> get _mainSink => _mainStreamController.sink;
Stream<MainEvent> get mainStream => _mainStreamController.stream;
MainBloc() {
_mainStreamController = StreamController<MainEvent>();
}
void showScreen() {
_mainSink.add(SomeEvent());
}
void showScreenTwo() {
_mainSink.add(SomeEventTwo());
}
}
abstract class MainEvent {}
class SomeEvent extends MainEvent {}
class SomeEventTwo extends MainEvent {}
Блок:
class Bloc {
StreamController<Event> _controller;
StreamSink<Event> get _sink => _controller.sink;
Stream<Event> get stream => _controller.stream;
Bloc() {
_controller = StreamController<Event>();
}
void secondEvent() async {
_sink.add(SecondEvent());
}
dispose() {
_controller.close();
}
}
abstract class Event {}
class InitialEvent extends Event {}
class SecondEvent extends Event {}
Ответ №1:
Не тестировал, но, возможно, попробуйте за пределами вашего MaterialApp
:
class MainView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamBuilder<MainEvent>(
stream: mainBloc.mainStream,
initialData: SomeEvent(),
builder: (
context,
snapshot,
) {
if (snapshot.hasData) {
MainEvent event = snapshot.data;
if (event is SomeEvent) {
return someView();
}
if (event is SomeEventTwo) {
return someView();
}
} else {
return Container(height: 0, width: 0);
}
},
);
}
}
вместо Widget someView(){ return ... }
Поведение setState иногда работает по-другому, если вы используете собственный метод сборки вместо объявления StatelessWidget.