Я новичок в Дарт / Флаттер, и после "посещения" курса Удеми все идет хорошо.До сих пор; -)
Как и в примере приложения в курсе Udemy, я использую шаблон BLOC.
Примерно так:
class App extends StatelessWidget {
Widget build(context) {
return AppBlocProvider(
child: MaterialApp(
(см. «AppBlocProvider»).который я позже использую, чтобы получить «AppBloc»)
Приложение, а также все экраны являются StatelessWidget.
AppBlocProvider расширяет InheritedWidget.Например:
class AppBlocProvider extends InheritedWidget {
final AppBloc bloc;
AppBlocProvider({Key key, Widget child})
: bloc = AppBloc(),
super(key: key, child: child);
bool updateShouldNotify(_) => true;
static AppBloc of(BuildContext context) {
return (context.inheritFromWidgetOfExactType(AppBlocProvider) as AppBlocProvider).bloc;
}
}
AppBlocProvider предоставляет «AppBloc», содержащий два дополнительных блока для разделения различных данных.Например:
class AppBloc {
//Variables holding the continous state
Locale appLocale;
final UserBloc userBloc;
final GroupsBloc groupsBlock;
В моем приложении у меня есть «GroupSearchScreen» только с одним полем ввода, где вы можете ввести фрагмент имени группы.При нажатии кнопки выполняется вызов REST API и возвращается список имен групп.
Как и в примере приложения, я также помещаю данные в поток.
В примере приложения данныеизвлечение и размещение в потоке выполняется в блоке itselve.На следующей строке создается Экран, который использует данные.Как это:
//Collecting data and putting it in the stream
storiesBloc.fetchTopIds();
//Creating a screen ths shows a list
return NewsList();
В моем случае, однако, есть два основных различия:
После сбора данных в GroupSearchScreen я вызываю / создаю GroupsListScreen, гдесписок групп должен отображаться с использованием обычной маршрутизации!Например:
// Добавить данные в поток («changeGroupList» предоставляет функцию добавления потока!) AppBloc.groupsBlock.changeGroupList (groups);// Вызов / создание экрана для отображения списка групп Navigator.pushNamed (context, '/ groups_list');
В созданном GroupsListScreen я получаю блок.Например:
Сборка виджета (контекст) {final AppBloc appBloc = AppBlocProvider.of (context);
Это маршруты:
Route routes(RouteSettings settings) {
switch (settings.name) {
case '/':
return createLoginScreen();
case '/search_group':
return createSearchGroupScreen();
case '/groups_list':
return createGroupsListScreen();
default:
return null;
}
}//routes
И "/ groups_list" указывает на эту функцию:
Route createSearchGroupScreen() {
return MaterialPageRoute(
builder: (context) {
//Do we need a DashboardScreen BLOC?
//final storiesBloc = StoriesProvider.of(context);
//storiesBloc.fetchTopIds();
return GroupSearchScreen();
}
);
}
Как видите,AppBlocProvider используется только один раз.(Я тоже столкнулся с этой проблемой; -)
Теперь к проблеме:
Когда GroupsListScreen начинает рендеринг списка, поток / снимок не содержит данных!
(См. «If (! Snapshot.hasData)»)
Widget buildList(AppBloc appBloc) {
return StreamBuilder(
stream: appBloc.groupsBlock.groups,
builder: (context, AsyncSnapshot<List<Map<String, dynamic>>>snapshot) {
if (!snapshot.hasData) {
Чтобы проверить все данные в блоке, которые были потеряны, я попытался не помещать данные в поток напрямую, а в переменную-член(в blloc!)
В GroupSearchScreen я поместил данные json в переменную-член в блоке.
Теперь, непосредственно перед тем, как GroupsListScreen начнет рендеринг списка, я беру данные (json) из блока, помещая я в поток, который все еще находится в блоке, все работает отлично!На снимке есть данные ...
Вот так (в GroupsListScreen):
//Add data to Stream
appBloc.groupsBlock.changeGroupList(appBloc.groupsBlock.groupSearchResult);
Почему поток «теряет» свои данные на пути от «GroupSearchScreen» к «GroupsListScreen ", когда обычной переменной-члена нет?Оба находятся в одном блоке!
В начале метода сборки GroupsListScreen у меня есть оператор print.Следовательно, я вижу, что GroupsListScreen - это сборка zwice.Это должно быть нормально, но может ли это быть причиной отсутствия данных в потоке?Прослушивается ли поток дважды?
Widget buildList(AppBloc appBloc) {
return StreamBuilder(
stream: appBloc.groupsBlock.groups,
Я пытался объяснить свою проблему таким образом, не предоставляя тонны кода.Но я не знаю, достаточно ли этого, чтобы дать подсказку, где я могу продолжить поиск ...
Обновление 16.04.2019 - РЕШЕНИЕ:
Я создаю свое первое приложение, используя другое приложение, показанное накурс Удеми ...
Самое важное различие между "его" приложением и my - это то, что он создает виджет, который прослушивает поток, а затем добавляет данные в поток.
Я добавляюданные в поток, а затем перейдите к виджету, который показывает данные.
К сожалению, я использовал RX-Dart "PublishSubject".Если вы прослушаете это, вы получите все данные, помещенные в поток, начиная с того времени, когда вы начали слушать!
RX-Dart "BehaviorSubject", однако, также даст вам последние данные, просто перед тем, как вы начали слушать.
Вот то поведение, которое мне было нужно здесь:
Поместить данные в поток
Создать виджет и начать слушать
Я могу посоветовать всем новичкам Флаттера прочитать оба эти очень хороших учебных пособия:
https://medium.com/flutter-community/reactive-programming-streams-bloc-6f0d2bd2d248
https://www.didierboelens.com/2018/12/reactive-programming---streams---bloc---practical-use-cases/
В первом из них оба упомянутых потока объяснены очень хорошо.