Программирование : Dart & Flutter по-русски
???????
Оно большое и сирашное, прост не смотрите и скрольте ниже)
???????
[
"Там как раз есть пример, у блока геттер:\n",
{
"type": "pre",
"text": "Stream get reducedStateComleteInit => this.state.where((AppState state) => state is CompleteInit).cast();",
"language": ""
},
"\n\nВот стримбилдером вы можете слушать этот гетер и срабатывать только на определенные состояния."
]
Игорь Кравченко
можешь написать задачу не с молоком и хлебом, а как-то более человечески, я попробую сделать пример для гитхаба?
???????
Я вам сейчас даже тз и желаемый интерфейс нарисую.
???????
[
{
"type": "pre",
"text": " Решить через 1 БЛоК и реактивно,\n выводя поочередно длины катетов\n и гипотенузы\n+---------------------------------+\n| Длина катета №1: [Поле ввода] |\n| |\n| Длина катета №2: [Поле ввода] |\n| |\n| [Кнопка посчитать гипотенузу] |\n| |\n| |\n| Квадрат катета №1: [Результат] |\n| |\n| Квадрат катета №2: [Результат] |\n| |\n| Длина гипотенузы: [Результат] |\n+---------------------------------+",
"language": ""
},
""
]
???????
Если что, длина гипотенузы равна sqrt(катет1^2 + катет2^2)
???????
Посчитать все, а потом все вывести - НЕЛЬЗЯ, задачка должна быть решена реактивно, а не императивно.
???????
Перерендеривать за зря огромную область с кучей виджетов или вообще в пустую - также НЕЛЬЗЯ.
???????
[
"Если так проще понять будет задачку, перед каждой математической операцией втыкайте ",
{
"type": "code",
"text": "await Future.delayed(Duration(seconds: 1))"
},
"\n\nНу и при таком раскладе нельзя заставить пользователя ждать дольше 2ух секунд, тобишь приложение должно выводить по ходу дела что оно посчитает)"
]
???????
Делайте репу публичной, я поправлю, если что)
???????
Условия понятны?) Они, если что, симулируют подавляющее количество встречающихся задачек, с которыми вы сталкиваетесь каждый день)
Игорь Кравченко
Я позадаю вопросы когда буду решать, сейчас не возле компа)
???????
Ага, тагайте, будет время - поправлю, я открыт для общения почти всегда когда не за рулем)
Mikhail Kolchanov
ивент подсчета (кидается при обновлении данных) 3 стэйта: 1. не все поля заполнены 2. Идет подсчет - вывод прогресс бара 3. Посчитано - вывод данных
Mikhail Kolchanov
ну окей. Если надо выводить поочередно, то добавить больше стейтов
Игорь Кравченко
При одном bloc будет рендериться вся страница при изменении одного поля
???????
Да, я для того пример и дал, чтоб человек посмотрел, как работать с кейсом, когда 1 событие порождает несколько стейтов.
???????
Не будет. Для того пример и дал.
???????
Сделайте как умеете, а я поправлю.
northelks
та всё равно на середине проекта стейт менеджмент будет ломаться, и будут строиться двухсторонние колбэки, кастомные стримы, билдеры..))
Игорь Кравченко
Билд будет вызываться
???????
Сделайте как умеете)
???????
А я покажу, как улучшить, чтоб сберечь батарейку и проц)
???????
Ну эт не оправдание, чтоб костылить)
northelks
это реальность)
???????
Ну да, все начинают с обсеров
???????
Беда, если обсеры мигрируют с проекта на проект
???????
и не учишься на своих ошибках, не делаешь выводы
???????
Я если смотрю на свой код полугодовалой давности сразу вижу косяки и думаю: "ну и мудаааааак"
???????
Ретроспектива для того и нужна)
???????
Задачку яж правильную дал, чтоб человек стейтами научился жонглировать?)
northelks
эмм, я особо не вчитывался)
northelks
очень много написано у вас тут)
???????
[
{
"type": "link",
"text": "https://t.me/rudart/87540"
}
]
???????
Чтоб разобрался, что 1 событие может порождать несколько стейтов.
northelks
нуу.. имхо достаточно глянуть на примеры с flutter_bloc
???????
Ну пусть попробует для начала сам)
northelks
а потом примеры provider
northelks
ну и потом просто про стримы
northelks
и этого вполне достаточно)
northelks
а так да, задачка норм ??
northelks
я бы усложнил, но это уже лишнее
Ivan Semenov
Какую файлову.ю структуру можете предложить для проекта на bloc паттерне? Все что пока нашел в интернете без матов сложно воспринять)
Яўген
Вот скажите, вот как так может, сначала окно загружается и выдает ошибку, а потом после горячей перезагрузки работает отлично? Я сдохну счас, если не пойму....
???????
Ну так сам чегот накостылил не того)
???????
Если проект не очень большой (скажем экранов 7), то:
Valentyn Stepanov
вы bloc свой используете или flutter_bloc?
Яўген
да я тупо по примеру делал, и костыли не юзал...
???????
Я реально сейчас убивать начну
???????
bloc и flutter_bloc это координально разные вещи, которые используют вместе, а не вместо
???????
flutter_bloc - это пару виджетов
???????
bloc - архитектура
Яўген
Не, это я сча начну убивать, после 7 часов бесперерывного поиска решения проблемы....
???????
под bloc берут либо flutter_bloc, либо provider
???????
В bloc вообще нет зависимостей от флатера, нет Stateless и Stateful Widget
???????
А в flutter_bloc и provider только они и есть
???????
bloc - архитектура flutter_bloc и provider - интерфейс
Ivan Semenov
Проект очень большой. Я предполагаю больше 1,000,000 строк. Архитектура Проект и Подпроекты. Мне нравятся DDD варианты.
???????
Под большой не посоветую, сори
???????
Думаеца мне, тут надо просто лезть на гитхаб и смотреть крупные проекты, не обязательно на флатере
Ivan Semenov
Я знаю как на redux browser такое сделать
Яўген
clean architecture?
Ivan Semenov
Случай когда можно асинхронно инжектить модули в проект. Допустим у вас модуль FlutterFans. Просто папку одноименную создаете, index файл с роутом, как на картинке и модуль в системе.
Ivan Semenov
папка с названием modules -> на самом деле там reducer и action
Ivan Semenov
Т.е. хотелось бы решение для простого добавления модулей в проект и их удаления парой действий.
???????
ну так у вас для этого есть export 'модуль_нейм.dart'; а также есть pubspec.yaml
Ivan Semenov
и что каждый роут прописывать в pubspec.yaml ?
Ivan Semenov
export 'модуль_нейм.dart'; это я не совсем понял. Я просто новичок в dart, но с typescript и es6-7 давно
???????
Что тут есть представление?)
???????
[
"3 строчки\n",
{
"type": "pre",
"text": "export './blocs/appBloc.dart';\nexport './blocs/loginBloc.dart';\nexport './blocs/dealsBloc.dart';",
"language": ""
},
""
]
???????
Импортируя этот файл, ты импортируешь сразу 3 этих
???????
также с экранами и всем-всем-всем
???????
Если тебя интересуют именно роутинг, то это делается через свойство MaterialApp
???????
там есть различные способы генерировать и обрабатывать роуты
???????
через pubspec.yaml действовать если ваше приложение состоит из разных крупных модулей.
???????
Я их называю "подсистемы")
???????
В общем тут различные уровни дробления выходят
FatShibe
А кто может помочь нормально вкорячить android sdk в флуттер на убунте?
Слава
Привет, а чем подводные камни использовать MVP и иметь в стейте методы интерфейса View и из них вызывать setState(){}?
Слава
https://github. com/fabiomsr/Flutter-StepByStep/blob/master/step5/lib/module/contacts/contact_list_view.dart
???????
Это называется Vanila архитектура, годится только для супер мелких приложений
???????
Уже на паре неплохо наполненных экранов вы запутаетесь в лапше из своих setState
???????
Поэтому во флатере есть такой супер полезный виджет как StreamBuilder
???????
Ну и MVP это не реактивный подход.
???????
Реактивщина это БЛоК, это Редакс и все такое.
Слава
Я думал, что это проще в обслуживании, чем делать поддержку множества Bloc'ов с их состояниями/эвентами и мапингом этого множества
???????
Ну попробуйте, набейте шишек, узнаете)
???????
В целом вам никто не запретит и накостылить вы можете что угодно)
???????
Идея этих вот блоков как раз в разграничении слоев абстракции (интерфейса и бизнес логики) и манипуляции Событиями и Состояниями
Слава
Ну вот, я хотел узнать, чем такой плох, потому что с виду смотрится не сложным для понимания
???????
[
{
"type": "pre",
"text": "\n +----------------+\n | Presentation |\n | Layer |\n | (UI) |\n +--+----------+--+\n | ^\n Event | | States\n Dispatch( ) | | mapEventToState()\n v |\n +--+----------+--+\n | |\n | BLoC |\n | |\n +--+----------+--+\n | ^\n Async requests | | Async response\nReposytory.fetch() | | await -> yield \n v |\n +--+----------+--+\n | Business Logic |\n | Layer |\n | (Backend) |\n +----------------+",
"language": ""
}
]
???????
Яж сказал, это императивный подход, а не реактивный, это раз. Во вторых с setState() на сложных приложениях и со StatefulWidget'ах неплохо так запутаетесь.
???????
[
"Можете попробывать посмотреть в сторону всевозможных ",
{
"type": "code",
"text": "scoped model"
},
" если блок и редакс вам путано пока."
]
???????
[
"у ScopedModel овердофига клонов, насколько помню, даже одной ",
{
"type": "code",
"text": "Provider"
},
" либой можно приготовить нечто подобное."
]
Слава
Спасибо, можете подсказать по моменту, когда и куда правильно инициализировать bloc объекты?
???????
Мне ленивенько открывать IDE. Но как готовлю я:
???????
1) либы bloc и provider
???????
2) есть пару глобальных блоков, которые создаются еще до вызова MaterialApp, блок приложения, блок пользователя, блок настроек. Они синглтоны и я могу слушать и диспатчить в них в любом месте приложения
Яўген
Если вам еще интересно. Вообщем, похоже я нашел хоть какое-то решение этой проблемы, и оно костыльное. Просто, вынес проблемный участок в отдельный метод, который возвращает результат форматирования даты. Сам паттерн форматирования у меня хранился в отдельном классе, но когда я перенес его непосредственно в код, где он юзается - все заработало. Так что теперь в том классе храниться просто стринговая переменная, а уже здесь она передается в переменную паттерн, которая в свою очередь вкладывается в дейтформат. Ну чет не оч, но пашет))
???????
3) локальные блоки экранов ты создаешь вместе со State'ом экрана (напоминаю, что все экраны, желательно, делать Stateful), и засовываешь в контекст с помощью Provider
???????
В результате, во всем последующем дереве экрана ты имеешь доступ к состояниям блока в любом месте. Ну и можешь диспатчить в него событиями.
???????
Крайне советую начать знакомство с блоком с примеров различных кейсов использования из оффициального репозитория.
???????
Некоторое время займет, но оно того стоит.
Слава
Используете DI для создания локальных Bloc'ов?
???????
Все изолировано друг от друга
???????
Яж скинул картинку
Anton ?? ? ??
По-моему пора делать FAQ
Anton ?? ? ??
Просто понять, что Bloc и провайдер заменяют stateful виджеты, где надо
Anton ?? ? ??
А зачем все экраны стейтфул, я думал это наоборот плохая практика, поэтому применяют блоки
Слава
Пытался смотреть примеры, но они показались слишком прощенными, которые охватывают пару кнопок и состояний. Поэтому мне кажется странным запихивать инициализацию Bloc'ов в начало App, потому что стоит ли делать их настолько глобальными, чтобы любые части могли подписаться на них, или все же это нормальная практика разработки на flutter.
???????
Ну есть глобальные
Слава
Тогда как их инициализировать, если они требуют зависимости для репозиториев с сетями и дисками?
Anton ?? ? ??
Посмотри пример реализации приложения погоды, где на 2 экрана 20 файлов
???????
Настройки, пользователь, приложение
???????
Можете как я синглтоном
???????
Можете провайдить от корня
???????
Они дергают синглтон репозитория
???????
А он содержит провайдеры
Слава
Вот это приложение для погоды? https://medium. com/flutter-community/weather-app-with-flutter-bloc-e24a7253340d
Влод
хз что у тебя от этого поменялось нооо ок. слава богу)
???????
[
{
"type": "link",
"text": "https://github.com/felangel/bloc/tree/master/examples"
}
]
Anton ?? ? ??
Оно даже разобрано, но разбираться и понимать нужноь часов 5
???????
[
"Если твой вопрос в том, как именно из блоков дергать бэк/локальное хранилище/железо, то можешь глянуть у меня класс ",
{
"type": "code",
"text": "Repository"
},
" и ",
{
"type": "code",
"text": "RepositoryProvider"
},
"\n\n",
{
"type": "link",
"text": "https://dartpad.dartlang.org/e3710bbb18d5b201a656811e5ef46ad8"
},
""
]
???????
[
"В данном примере ты из любого блока можешь вызвать: \n",
{
"type": "pre",
"text": "Repository().simulateDelayProvider.fetch();",
"language": ""
},
""
]
Слава
Спасибо. Интересовало куда именно вставлять инициализацию Bloc. Теперь думаю в DI проставлять методы инициализации для используемых компонентов и вызывать di.resolve в то место, где нужно
???????
Зачем тебе его инициализировать?
Слава
Чтобы зависимости проставить
???????
У БЛоКов нет никаких сложных конструкторов и длительной инициализации
???????
[
"Просто при создании State'а StatefulWidget'а\nты создаешь экземпляр\n",
{
"type": "code",
"text": "final MyBloc myBloc = new MyBloc();"
},
""
]
???????
Чтоб получить к нему доступ во всех низлижайших виджетах ты берешь ОДНУ из двух библиотек flutter_bloc или provider
Слава
Сложных и длительных конструкторов и не должно от этого быть. Это просто другой способ управления зависимостями, через обращение с сигнлтонами нужных объектов или через обращение к ним как к зависимостям самого класса
???????
Собственно создал финальным в виджете в котором он должен жить (часто это экран), засунул в провайдер, где надо достал из контекста
???????
Все остальные способы, передачи зависимостей или еще чего - ведут к головной боли из за того, что у тебя получается спагетти код,
???????
По сути для взаимодействия с блоком из интерфейса у тебя есть: 1) dispatch - через него ты генерируешь события 2) .state - поток с состояниями которые ты слушаешь StreamBuilder'ом
Yuniia
кто пользовался showTimePicker, ка нормально получить значение?
???????
Всего 2 эти вещи гарантируют минимальную связаность и максимальное разделение абстракций
Yuniia
и вообще как работать с TimePicker?
Яўген
вообщем, пообщался с человеком, мы в этом покапались, и там походу какой-то баг... Мы еще будем разбираться....
Слава
Про взаимодействие понял, но не понял почему должен использовать синглтоны как зависимости, вместо установки их через di
Слава
И будет final LoginBloc = Di.injector.get ();
???????
Это лишь мой способ для глобального хранения глобальных блоков
???????
Это тебе тоже не надо
???????
Этим занимается Provider
???????
Он делает именно то что ты хочешь, но без лишних костылей
???????
А именно засовывает классы в контекст дерева виджетов.
Слава
Ок, спасибо. А как много ответственности должно быть на самом блок? Допустим, если на экране несколько разных независимых список, то стоит под каждый список создавать отдельный Bloc или Bloc под текущее отображение, которое может управлять несколькими списками?
???????
Вот что ты хочешь
Слава
Ну да, тут уже без разницы куда сунуть resolve
???????
[
{
"type": "link",
"text": "https://youtu.be/1t-8rBCGBYw"
}
]
???????
Вот, краткий сказ об InheritedWidget
???????
Потом резюме, что это путаная штука
???????
Вот вам Provider, тут все просто, тут то что вам надо
???????
И все это за 1:30
Слава
Спасибо за помощь, буду еще изучать
???????
В общем 2 либы: bloc и provider, этого хватит за глаза если взять вместе.
???????
Если будет сложно, то то что вы изначально планировали-изобретали - scoped_model
???????
[
"Это уже как сами решите.\nЯ делаю блок под конкретную область задач, а это, как правило - экран. Тобишь блок отвечает за целый экран.\n\nА так, это не регламентируется и хозяин-барин.\nБлок лишь говорит о том, как связывать Presentation Layer с Buisiness Logic Layer, а как надробите - вам решать.\n\nЯ делаю экраны Stateful (перестал делать Stateless после выхода веба и первого ресайза окна браузера), в его State и создаю ",
{
"type": "code",
"text": "final MyBloc"
},
""
]
???????
Никто не запрещает создавать блок под какойнить хитрый виджет, скажем календарь.
Ivan Semenov
Нарисовал рандомный пример файловой структуры bloc проекта..
Ivan Semenov
Отдельный файл роуты, в котором перенаправление на screen. В screen import модуля.
Ivan Semenov
Модель, как я понял, это просто описание полей, статические поля и геттеры, сеттеры
Ivan Semenov
Bloc - чтобы fetchiть данные
Ivan Semenov
Provider - между bloc и widget доставление данных. Widgets - отрисовка виджетов модуля.
Evgenii Egorov
Провайдер доставляет данные в блок, блок отвечает за логику и обработку, виджетс(экран отрисовки) берет данные из блока
Evgenii Egorov
[
"1_MqYPYKdNBiID0mZ-zyE-mA.png\n",
{
"type": "link",
"text": "https://miro.medium.com/max/1200/1*MqYPYKdNBiID0mZ-zyE-mA.png"
}
]
Ivan Semenov
Заметил еще события обмена данными между bloc и widget обособляют в отдельный файл. Например OrderEvents.dart
Ivan Semenov
Еще отдельно создают state файл OrderState.dart. Типа состояние компонента над которым идет работа ( отрисован, загружается и пр..)
Ivan Semenov
Repository - это api получается. Там взаимодействие с локальным хранилищем, бекендом, внешними API
Влод
Почему страницы отдельно от остального модуля
Hellomik
хей кто знает как перевернуть картинку (а именно файл)
Ivan Semenov
Потому что в странице может быть реализовано несколько модулей. Модули могут быть большие и самые маленькие. Сейчас скрин скину
Ivan Semenov
Это типа Atomic Design - atoms, moleculs (common/widgets); organisms - modules и pages - screens
Ivan Semenov
Страница списка заказов может сразу содержать в себе список заказов, корзину, какую-то сложную форму поиска, футер. Пример не real world. Я это к тому, что модули бывают разными. А screens (страницы) простая понятная вещь.
Влод
а хех. я только от совы раньше такие слова слышал
Anton ?? ? ??
как было просто с презентерами в нативе...
Ivan Semenov
А что это значит?
Ivan Semenov
Atomic Design - это, скорее, в броузере возня.
Ivan Semenov
Такая структура файловая должна легко давать удалять сущности или создавать новые модифицированные. Надоел модуль Orders - заменил на OrdersV2 по такому принципу. Вот я определяюсь с файловой структурой и собираюсь писать CLI, чтобы создавать модули парой строчкой в консоли..
Влод
тоже всегда делаю как делается)
Ivan Semenov
Даа не ну пофиг на Атомик на эти мудацкие названия. Просто расписал как вижу архитектуру. Может кто согласен, кто нет
Hellomik
как с image получить File ?
Anton ?? ? ??
Если ты имеешь в виду launchscreen
KeepOnSmiling ??
Ребят, если кто помнит у меня трабла была, что анимация FadeTransition не срабатывала, да и походу ваще никакая не срабатывала. Так вот проблема оказалась в том, что в initState чтобы анимация работала нужно вызывать: "super.initState();", но обязательно после контроллера, а я вызвал до создания контроллера. Объясните плз, а почему так?
KeepOnSmiling ??
Как только super.initState(); поместил в конец initState - так всё запустилось. Но почему это так важно? Что там такого важного в этом родительском super.initState()?
KeepOnSmiling ??
[
"Есть такой вопрос ещё. Хочу в главном классе хранить ссылки на определённые Stateful-виджеты, чтобы в любой момент произвольные ребилдить. \nКак можно сделать такую ссылку? \nВ Stateful-widget'ах я создал:\n\n",
{
"type": "pre",
"text": "void rebuild() { setState( (){} ); }",
"language": ""
},
"\n\nНо как теперь до них доступиться?"
]
KeepOnSmiling ??
Попытка вот такая:
|