Привет, я Андрей, работаю Flutter разработчиком в компании Финам.
В этой части мы сделаем рефакторинг проекта и подключим клиентское Flutter приложение к сервису Umka.
Рефакторинг проектa
Репозиторий для описания и сгенерированного кода проекта Umka
Выделим в отдельный проект описание сервиса Umka на IDL Progobuf и сгенерированные для сервиса файлы. Поместим код в репозиторий umka_proto на Github.
Репозиторий для сервиса Umka
Удалим из проекта Umka Service описание umka.proto и папку для сгенерированного базового Dart кода сервиса lib/generated.
Репозиторий umka_service.
Фактически здесь у нас осталось только 2 файла:
-
Код для серверного приложения service.dart
-
Код для извлечения вопросов из импровизированной базы questions_db_driver.dart
Базовый код подключим в виде зависимости umka_proto:

Теперь все готово для подключения к сервису мобильного Flutter приложения.
Мобильное Flutter приложение для работы с сервисом Umka
Целью даной серии не является описание процесса создания Flutter приложения, поэтому я дам краткий обзор как оно устроено и ссылку на исходный код.
Umka-Flutter это не полноценное мобильное приложение, а лишь прототип для демонстрации использования сервиса Umka, создание которого мы рассмотрели в предыдущих 3х частях цикла, и который также является демонстрационным прототипом сервиса на основе технологии gRPC.
Подробнее мы рассмотрим код отвечающий за взаимодействие с gRPC сервисом.
Для управления состоянием я выбрал Bloc, конкретнее Cubit, как один из наиболее популярных и не очень «вербозных» подходов.
На главном экране расположено 3 вкладки:
-
Quiz, отправка ответа на случайный вопрос.
-
Tutorial, ответы на список вопросов, полученных от сервиса, с индикацией правильного ответа.
-
Exam, импровизированное прохождение экзамена.

Структура проекта мобильного приложения
Подключение нашей библиотеки umka_proto делается точно также как и для сервиса:

Файловая структура проекта выглядит так:

У нас есть home_screen.dart в папке lib/ui/home где реализована навигация по трём вкладкам, а также 3 директории для «фич»: lib/ui/quiz, lib/ui/tutorial и lib/ui/exam, в каждой из которых присутствуют .dart файлы с кодом для:
-
хранения состояния (*state.dart)
-
бизнес логики и изменения состояния (*cubit.dart)
-
отображения пользовательского интерфейса (*view.dart)
Удалённые вызовы сервиса Umka описаны в файле lib/services/umka_service.dart. Код вызовов практически полностью идентичен тому, который мы рассматривали в предыдущих трёх частях серии для терминального клиента class UmkaTerminalClient.
Остальные файлы в проекте являются стандартными для Flutter проекта или вспомогательными.
Код мобильного приложения Umka
ссылка на репозиторий с исходным кодом проекта
Логика работы
Работа с удаленными вызовами сервиса осуществляется исключительно в файлах *cubit.dart:
-
Делаем запрос нужной информации на сервисе или отправляем сервису данные.
-
Получаем от сервиса ответ.
-
В зависимости от полученного ответа меняем состояние
class *Stateдля соответствующей «фичи» нужным образом, отправляя новое состояние методамиemit(newState)расположенными вclass *Cubit.
Вкладка Quiz
Демонстрация работы
-
Вводим имя.
-
Нажимаем кнопку «Get Random Question».
-
Отображается вопрос, на который мы вводим ответ.
-
Отправляем ответ на сервис.
-
Сервис оценивает ответ и присылает результат.
И так «по кругу» сколько угодно раз.

За логику работы отвечает класс QuizCubit, находящийся в файле lib/ui/quiz/quiz_cubit.dart.
По заполнению поля с именем появляется кнопка «Get Random Question» и после её нажатия срабатывает метод getRandomQuestion(), в котором происходит удаленный вызов на сервис:
final question = await umkaService.getRandomQuestion(student);.
Вопрос запоминается в QuizState и отображается для студента. Он заполняет поле с ответом и отправляет его сервису:
final evaluation = await umkaService.sendAnswer(answer);.
В ответе evaluation приходит результат правильным был ответ или нет, который и отображается студенту.
Вкладка Tutorial
Работает это так:
-
Вводим имя и нажимаем кнопку «Start».
-
С сервиса начинают потоком поступать вопросы, примерно каждые 2 секунды.
-
Вводим ответ на каждый вопрос.
-
«Чекаем» ответы, и сразу видим результат верно или нет.
-
Исправляем ошибочные ответы.

Работа с сервисом происходит в классе TutorialCubit:

Метод takeTutorial() срабатывает по нажатии кнопки «Start». На строке №20 мы «подписываемся» на поток вопросов от сервиса и обрабатываем их по одному. С сервиса «прилетают» уже отвеченные вопросы, поэтому после проставления галочки, мы немедленно видим результат.
Вкладка Exam
«Экзамен» проводится следующим образом:
-
«Студент» вводит своё имя и нажимает кнопку готовности к экзамену.
-
Сервис присылает все экзаменационные вопросы и первый из них отображается на экране.
-
После ввода ответа экзаменуемый кнопкой «Send…» отправляет ответ в поток соединения с сервисом.
-
Появляется следующий вопрос … .
-
После отправки ответа на последний вопрос сервис присылает итоговую «оценку».

Взаимодействие с сервисом происходит в классе ExamCubit:

Нажатие кнопки «Send …» запускает метод takeExam(String name). Вопросы запрашиваются на сервисе и сохраняются в объекте exam:
final exam = await umkaService.getExam(state.student);
Создается соединение с сервисом, на который передается стрим для для отправки ответов:
final evaluation = await umkaService.takeExam(state.student.name, answersStream!.stream);
После получения всех ответов, сервис вернет «оценку», которая помещается в объект evaluation.
Метод sendAnswer(String enteredAnswer) просто добавляет ответы в стрим, переданный сервису.
Запускаем сервис и приложение на локальном компьютере
Я приведу для примера набор команд, с помощью которых можно склонировать исходники и запустить приложение и сервис, чтобы можно было всё «пощупать руками», «погулять» по коду и посмотреть логи.
Чтобы всё сработало на компьютере должны быть установлены Git и Dart и Flutter. Также запустите симулятор или эмулятор мобильного устройства или подсоедините реальное. Командой flutter devices убедитесь, что мобильное устройство видно и находится первым в списке доступных.

-
Открываем терминал, создаем директорию
umka_demoи переходим в нее:
mkdir umka_demo & cd umka_demo
-
Клонируем исходники сервиса:
git clone https://github.com/Umka-org/umka_service.git
-
Клонируем исходники мобильного приложения:
git clone https://github.com/Umka-org/umka_flutter_app.git
-
Переходим в папку с сервисом, «подтягиваем» зависимости и запускаем сервис:
cd umka_service && pub get && dart lib/service.dart
-
Открываем рядом второй терминал, переходим в папку с мобильным приложением, добавляем в проект нужные библиотеки и запускаем мобильное приложение:
cd umka_demo/umka_flutter_app && flutter pub get && flutter run
Если все сработало, наслаждаемся, если же что-то пошло не так, сильно не злимся, а устраняем проблемы. Я проверил работоспособность приведённых команд на маке и Ubuntu.
На этом данная серия из четырех статей завершена. Надеюсь было полезно. Спасибо всем, кто дочитал до конца и поддерживал меня.
До встречи!
ссылка на оригинал статьи https://habr.com/ru/articles/580000/
Добавить комментарий