Android
Download
1 / 31

Создание удобной архитектуры Android- приложения - PowerPoint PPT Presentation


  • 183 Views
  • Uploaded on

Создание удобной архитектуры Android- приложения. Александр Османов Android- разработчик, DataArt , Воронеж. Постановка задачи. Часто во время работы приложения необходимо выполнять продолжительные задачи в фоне: Выполнение HTTP запроса к серверу Математический расчет

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' Создание удобной архитектуры Android- приложения' - alexa-carlson


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
Android

Создание удобной архитектуры Android-приложения

Александр Османов

Android-разработчик, DataArt, Воронеж


Постановка задачи

  • Часто во время работы приложениянеобходимо выполнять продолжительные задачи в фоне:

    • Выполнение HTTP запроса к серверу

    • Математический расчет

  • После выполнения задачи необходимо уведомить UI о завершении, чтобы UI смог обновиться.

  • Во время выполнения задачи может понадобиться узнать прогресс выполнения задачи


Почему нетривиально?

  • Часто нужна возможность контроля над очередностью выполнения задач, возможность отмены и отслеживания прогресса выполнения

  • Жизненный цикл визуальных компонентов часто ставит палки в колеса

  • До сих пор нету официально рекомендованной Google организации взаимодействия с сервисом:

    • Broadcasts/Local broadcasts

    • Binding

    • ResultReceiver

    • createPendingResult


Как UI может узнать, что что-то происходит?

  • «Управляемые» платформой — компоненты, реализующие ContentObserver. В случае использования приложением ContentProvider, а также адаптеров курсора подобные обновления достаются нам «бесплатно». О них речь не пойдет.

  • Уведомления, реализованные в приложении — наши нестандартные уведомления, когда мы просто хотим отправить результат или прогресс выполнения фоновой задачи в UI.


Asynctask
AsyncTask?

  • Самый очевидный и простой способ для новичка

  • Позволяет легко указывать, какой код исполнять в фоновом потоке, какой в UI потоке

  • Позволяет публиковать прогресс операции

  • Код пишется легко и быстро


Asynctask1
AsyncTask

  • Смешивание кода, посылающего HTTP запросы, с кодом, отвечающим за UI в вашей Activity

  • Потеря контекста при пересоздании activity

  • Сложно контролировать очередность выполнения запросов

  • Вы не можете управлять процессом, в котором будет выполняться задача


Service
Service!

  • Специально созданный для такого рода задач компонент с независимым жизненным циклом

  • Однако, требует дополнительной работы, чтобы организовать двустороннее общение с Activity


Наброски нашего фреймворка

  • Command — каждая задача, которую мы хотим выполнять в фоне — отдельный класс-команда

  • Command processor — сервис, отвечающий за планирование и выполнение команд

  • ContentProvider — поможет реализовать хранение данных + управляемые обновления UI.

  • Уведомления UI?


Broadcast
Broadcast

  • После выполнения работы сервис посылает broadcast-сообщение с результатом работы

  • UI получает сообщения при помощи BroadcastReceiver и ожидает входящих сообщений.


Broadcast1
Broadcast

  • Преимущества

    • Легко использовать

    • Легко привязать к жизненному циклу Activity

    • Могут работать между процессами

  • Недостатки

    • Необходимо предпринять меры по защите сообщений, либо установив разрешения, либо ограничив принимающие пакеты

    • Также сообщения потенциально могут быть присланы извне другими приложениями. Опять необходимо предпринимать меры.

    • Проходит через системную очередь сообщений


Localbroadcastmanager
LocalBroadcastManager

  • Преимущества

    • Легко использовать

    • Легко привязать к жизненному циклу Activity

    • Не нужно думать о безопасности

  • Недостатки

    • Не могут работать между процессами


Resultreceiver
ResultReceiver

  • Generic interface for receiving a callback result from someone. Use this by creating a subclass and implement onReceiveResult(int, Bundle), which you can then pass to others and send through IPC, and receive results they supply with send(int, Bundle).

  • Мы можем отправить экземпляр ResultReceiverпрямо как extra в Intent нашему сервису.


Resultreceiver1
ResultReceiver

  • Преимущества

    • Работает как локально, так и через процессы

    • Не нужно думать о безопасности

  • Недостатки

    • Немного сложнее привязать к жизненному циклу Activity


Наброски нашего фреймворка

  • Command — каждая задача, которую мы хотим выполнять в фоне — отдельный класс-команда

  • Command processor — сервис, отвечающий за планирование и выполнение команд

  • ContentProvider — поможет реализовать хранение данных + управляемые обновления UI.

  • ResultReceiver — для возвращения результата работы фоновой задачи

  • Реестр выполняющихся в данный момент операций


Command processor
Command Processor

  • Каждая задача, которую необходимо выполнить, будет инкапсулирована в класс-команду

  • Каждая команда будет реализовывать Parcelable для более удобной передачи ее сервису

  • Для каждой выполняемой команды будет создаваться уникальный идентификатор

  • Команды образуют иерархию, где базовый класс инкапсулирует ResultReceiverи реализует общие методы, например, sendResult(intresultCode, Bundle data).


Command processor1
Command Processor

  • В качестве процессора команд будет выступать Service

    • IntentService

    • Своя реализация сервиса с использованием ExecutorService

  • Команды будут передаваться сервису в виде extras в Intent

  • Сервис будет просто извлекать их и запускать в новом потоке (потоке из пула)

  • Сервис также может хранить соответствие идентификатор-выполняемая команда для возможности реализации отмены команды


Command processor2
Command Processor

BaseCommandcommand = intent.getParcelableExtra(EXTRA_COMMAND);

ResultReceivercallback = intent.getParcelableExtra(EXTRA_STATUS_RECEIVER);

command.execute(intent, context, callback);


Command processor3
Command Processor

ExecutorService

Service

Command 1

ResultReceiver


Servicehelper
ServiceHelper

  • ServiceHelper — это промежуточный слой между UI и сервисом, скрывающий рутину по созданию интентов сервису и предоставляющий нашему UI лишь набор бизнес методов для вызова.

  • Также он координирует ответы от сервиса и содержит информацию о командах, выполняющихся в данный момент.

  • ServiceHelper«живет» в Application scope приложения


Servicehelper1
ServiceHelper

  • Дополнительные методы ServiceHelper

    • isExecuting(intrequestId)

    • cancelCommand(intrequestId)

    • addListener(ServiceCallbackListener listener)

    • removeListener(ServiceCallbackListener listener)

  • Пример:

    • public intaskServer(String question)


Принцип работы

  • Activity вызывает бизнес-метод ServiceHelper

  • ServiceHelper генерирует и сохраняет ID запроса, запоминает, что данная команда выполняется

  • Собирает Intent, в который вкладывет ResultReceiver, экземпляр команды и отправляет сервису

  • Когда сервис завершает операцию, ServiceHelper отвечает за то, чтобы все активные Activity получили результат


Servicecallbacklistener
ServiceCallbackListener

  • Слушателем может быть что угодно. Для удобства я сделал базовый класс Activity, выступающий в роли слушателя и подписывающийся на обновления при запуске.

  • Это позволяет в реализациях Activity просто переопределить метод onServiceCallback и реализовать в нем логику аналогично тому, как это делается со стандартными callback-методами системы.


Servicecallbacklistener1
ServiceCallbackListener

  • void onServiceResult(intrequestId, Intent intent,intresultCode, Bundle resultData);

    • requestIdпозволяет нам идентифицировать конкретный запрос

    • Intent позволит нам идентифицировать класс команды, если нас не интерует конкретный запрос

    • resultCode, resultData – позволят обработать результат выполнения команды


Принцип работы

Application

Activity

Listener

ServiceHelper

Receiver

Command

Service

Provider

Comand 1

Comand 2


Отложенная проверка

  • Имея ID запроса, мы можем выполнять отложенную проверку. Представим последовательность:

    • пользователь запустил действие, запустилась крутилка

    • закрыл приложение на 2 минуты

    • действие уже выполнилось

    • пользователь открыл снова

  • тут мы проверяем в onResume, выполнилась ли операция, и убираем крутилку

    • т. е., просто вызываем getServiceHelper().isPending(requestId), если нам это нужно.


Расширение №1. Отмена выполнения

  • В базовый класс запрос добавим метод cancel()

  • Добавим метод cancelCommand(intcommandId) в ServiceHelper

  • Метод посылает Intent в сервис, который находит команду по идентификатору и вызывает cancel()


Расширение №2. Прогресс операции

  • Добавляем новый resultCodeпомимо SUCCESS и ERROR, и все.


Сторонние библиотеки, которые нам помогут

  • Ottoот Square – очень удобная реализация event bus. В нашей схеме подойдет для передачирезультатов команды

    • Использует reflection

    • Работает только в одном процессе и одном потоке

  • Groundy – неплохая библиотека, реализующая command processor на основе генерации кода


В итоге мы получили нам помогут

  • Гибкую архитектуру для выполнения задач в фоне с поддержкой уведомлений UI

  • Поддержка жизненного цикла Activity

  • Возможность легко вынести выполнение задач в отдельный процесс, просто выставив атрибут сервису в манифесте

  • Возможность управлять стратегией выполнения задач меняя реализацию сервиса (IntentService vs ExecutorService)

  • Расширяемость


Пример исходного кода нам помогут

  • Github - http://goo.gl/4voFM


Спасибо за внимание! нам помогут

Вопросы?


ad