android studio фоновое приложение

Служба (Service)

Службы (Сервисы) в Android работают как фоновые процессы и представлены классом android.app.Service. Они не имеют пользовательского интерфейса и нужны в тех случаях, когда не требуется вмешательства пользователя. Сервисы работают в фоновом режиме, выполняя сетевые запросы к веб-серверу, обрабатывая информацию, запуская уведомления и т.д. Служба может быть запущена и будет продолжать работать до тех пор, пока кто-нибудь не остановит её или пока она не остановит себя сама. Сервисы предназначены для длительного существования, в отличие от активностей. Они могут работать, постоянно перезапускаясь, выполняя постоянные задачи или выполняя задачи, требующие много времени.

Клиентские приложения устанавливают подключение к службам и используют это подключение для взаимодействия со службой. С одной и той же службой могут связываться множество клиентских приложений.

Android даёт службам более высокий приоритет, чем бездействующим активностям, поэтому вероятность того, что они будут завершены из-за нехватки ресурсов, заметно уменьшается. По сути, если система должна преждевременно завершить работу запущенного сервиса, он может быть настроен таким образом, чтобы запускаться повторно, как только станет доступно достаточное количество ресурсов. В крайних случаях прекращение работы сервиса (например, задержка при проигрывании музыки) будет заметно влиять на впечатления пользователя от приложения, и в подобных ситуациях приоритет сервиса может быть повышен до уровня активности, работающей на переднем плане.

Используя сервис, можете быть уверены, что ваши приложения продолжат работать и реагировать на события, даже если они в неактивном состоянии. Для работы службам не нужен отдельный графический интерфейс, как в случае с активностями, но они по-прежнему выполняются в главном потоке хода приложения. Чтобы повысить отзывчивость вашего приложения, нужно уметь переносить трудоёмкие процессы (например, сетевые запросы) в фоновые потоки, используя классы Thread и AsyncTask.

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

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

Запущенные сервисы всегда имеют больший приоритет, чем бездействующие или невидимые активности, поэтому менее вероятно, что их работа завершится преждевременно при распределении ресурсов. Единственная причина, почему Android может досрочно остановить Сервис, — выделение дополнительных ресурсов для компонентов, работающих на переднем плане (как правило, для активностей). Если такое случится, ваш сервис автоматически перезапустится, когда будет достаточно доступных ресурсов.

Когда сервис напрямую взаимодействует с пользователем (например, проигрывая музыку), может понадобиться повысить его приоритет до уровня активностей, работающих на переднем плане. Это гарантия того, что сервис завершится только в крайнем случае, но при этом снижается его доступность во время выполнения, мешая управлять ресурсами, что может испортить общее впечатление от приложения.

Приложения, которые регулярно обновляются, но очень редко или нерегулярно взаимодействуют с пользователем, можно назвать первыми кандидатами на реализацию в виде сервисов. Проигрыватели MP3 и приложения, отслеживающие спортивные результаты, — примеры программ, которые должны постоянно работать и обновляться без необходимости отображать активность.

Создание службы

Чтобы определить службу, необходимо создать новый класс, расширяющий базовый класс Service. Можно воспользоваться готовым мастером создания класса для сервиса в Android Studio. Щёлкаем правой кнопкой мыши на папке java (или на имени пакета) и выбираем New | Service | Service:

service2

В следующем окне выбираем имя сервиса (флажки оставляем) и нажимаем кнопку Finish.

service3

При этом сервис автоматически зарегистрируется в манифесте в секции .

Если бы мы убрали флажки на экране мастера, то оба атрибута имели бы значение false. Например, атрибут exported даёт возможность другим приложениям получить доступ к вашему сервису.

Имеются и другие атрибуты, например, permission, чтобы сервис запускался только вашим приложением.

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

Жизненный цикл служб

Подобно активностям служба имеет свои методы жизненного цикла:

service

Для быстрого создания заготовок нужных методов используйте команду меню Code | Override Methods. или набирайте сразу имя метода, используя автодополнение.

Реализуя эти методы обратного вызова в своей службе, вы можете контролировать жизненные циклы службы. В полном жизненном цикле службы существует два вложенных цикла:

Из своего приложения службу можно запустить вызовом метода Context.startService(), остановить через Context.stopService(). Служба может остановить сама себя, вызывая методы Service.stopSelf() или Service.stopSelfResult().

Можно установить подключение к работающей службе и использовать это подключение для взаимодействия со службой. Подключение устанавливают вызовом метода Context.bindService() и закрывают вызовом Context.unbindService(). Если служба уже была остановлена, вызов метода bindService() может её запустить.

Методы onCreate() и onDestroy() вызываются для всех служб независимо от того, запускаются ли они через Context.startService() или Context.bindService().

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

В метод обратного вызова onBind() передают объект Intent, который был параметром в методе bindService(), а в метод обратного вызова onUnbind() — объект Intent, который передавали в метод unbindService(). Если служба разрешает связывание, метод onBind() возвращает канал связи, который используют клиенты, чтобы взаимодействовать со службой. Метод обратного вызова onRebind() может быть вызван после onUnbind(), если новый клиент соединяется со службой.

Запуск сервиса и управление его перезагрузкой

В большинстве случаев также необходимо переопределить метод onStartCommand(). Он вызывается каждый раз, когда сервис стартует с помощью метода startService(), поэтому может быть выполнен несколько раз на протяжении работы. Вы должны убедиться, что ваш сервис это предусматривает.

Метод onStartCommand() заменяет устаревший метод onStart(), который использовался в Android 2.0. В отличие от onStart() новый метод позволяет указать системе, каким образом обрабатывать перезапуски, если сервис остановлен системой без явного вызова методов stopService() или stopSelf().

Службы запускаются в главном потоке приложения; это значит, что любые операции, выполняющиеся в обработчике onStartCommand(), будут работать в контексте главного потока GUI. На практике при реализации сервиса в методе onStartCommand() создают и запускают новый поток, чтобы выполнять операции в фоновом режиме и останавливать сервис, когда работа завершена.

Такой подход позволяет методу onStartCommand() быстро завершить работу и даёт возможность контролировать поведение сервиса при его повторном запуске, используя одну из констант.

Обратите внимание, что при окончании всех операций каждый из этих режимов требует явной остановки сервиса с помощью методов stopService() или stopSelf().

Режим перезапуска, который вы указываете в качестве значения, возвращаемого методом onStartCommand(), будет влиять на параметры, передаваемые при последующих вызовах.

Изначально намерение выступает в качестве параметра, который передастся в метод startService() при запуске сервиса. После перезапуска системой он может иметь значение null (если установлен режим START_STICKY) или оригинальное (если установлен флаг START_REDELIVER_INTENT).

Параметр flag может помочь узнать, как именно был запущен сервис:

Запуск и остановка служб

Чтобы запустить службу, в клиентском приложении необходимо вызывать метод startService(). Существует два способа вызова службы:

Пример для явного вызова службы с именем MyService:

Также можно явно определить службу, создав экземпляр класса этой службы.

Пример неявного вызова службы:

Чтобы использовать этот пример, необходимо включить константу SERVICE_ACTION, идентифицирующую службу, в класс MyService, например:

Используйте фильтр намерений, чтобы зарегистрировать его как провайдера SERVICE_ACTION. Если служба потребует разрешений, которые не имеет ваше приложение, то запрос вызовет исключение SecurityException.

Как только сервис завершил выполнение тех действий, для которых он запускался, вы должны вызвать метод stopSelf() либо без передачи параметра, чтобы ускорить остановку работы, либо передав значение startId, чтобы убедиться, что задачи выполнены для всех экземпляров, запущенных с помощью вызова startService(), как показано в следующем фрагменте:

Явная остановка сервиса по завершении необходимых задач позволяет системе получать обратно ресурсы, которые в ином случае оставались бы заняты. Поскольку приоритет сервисов повышенный, система, как правило, не завершает их работу, поэтому её окончание по собственной инициативе может существенно улучшить эффективность использования ресурсов вашим приложением.

Для остановки работы используйте метод stopService(), передавая ему объект Intent, определяющий нужный сервис.

Если метод startService() вызывается для сервиса, который уже работает, обработчик onStartCommand(), принадлежащий объекту Service, будет вызван повторно. Вызовы startService() не накапливаются, поэтому единственный вызов метода stopService() завершит работу сервиса, неважно, сколько раз производился вызов startService().

Давайте создадим практическое приложение для работы со службой. Наша служба будет запускать на воспроизведение музыкальный файл, который будет проигрываться в фоновом режиме. Управлять службой можно будет из активности. Создайте новый проект. Для службы создайте отдельный класс PlayService. Служба будет загружать музыкальный файл sample.mp3 из каталога res/raw/ (разместите там свой MP3-файл).

PlayService.java

Зарегистрируем службу в файле манифеста.

В файле разметки для активности определим две кнопки: Старт и Стоп:

В классе активности в обработчиках событий кнопок будем вызывать методы startService() и stopService() для управления службой.

Запущенная служба будет выполняться независимо от состояния активности, несмотря на то, что эти компоненты находятся в одном приложении: если её завершить, служба все равно останется работать.

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

Приёмник регистрируется в манифесте с именем действия BOOT_COMPLETED:

Пример для Kotlin

Класс для службы, которая будет генерировать случайные числа через определённый промежуток времени. Не забудьте прописать службу в манифесте.

Разместите на экране активности три кнопки: запуск, остановка и статус службы. Код для активности.

Список всех запущенных сервисов

Ущемление прав службы

Google последовательно борется с ограничениями для служб, урезая их возможности. Делается это для того, чтобы службы не висели в памяти бесконечно долго и тратили заряд батареи. Ограничение возможностей происходит постепенно от версии к версии. В последних версиях уже можно столкнуться с примерами, когда выкидывается исключение при неправильной работе с службами.

Для решения проблем следует изучить такие вещи как JobScheduler, Firebase Job Dispatcher, WorkManager. Также появилось понятие Foreground service.

Системные службы

Кроме создания собственных сервисов, вы можете использовать системные сервисы. Вот небольшой список:

Источник

Руководство по фоновой работе в Android. Часть 1

О фоновой работе приложений в Android есть много статей, но мне не удалось найти подробного руководства по реализации работы в фоне – думаю, из-за того, что появляется все больше новых инструментов для такой работы. Поэтому я решил написать серию статей о принципах, инструментах и методах асинхронной работы в приложениях под Android.

image loader

Будет несколько частей:

Начнем с первой части.

Основы UI

Первое, что следует понять, – почему мы вообще беспокоимся о работе в фоне в мобильных приложениях.

Во всех приложениях для Android есть хотя бы один поток, на котором происходит прорисовка UI и обработка пользовательского ввода. Поэтому он и называется потоком UI или главным потоком.

Каждый метод жизненного цикла каждого компонента вашего приложения, включая Activity, Service и BroadcastReceiver, исполняется на UI-потоке.

Человеческий глаз преобразовывает сменяющиеся изображения в плавное видео, если частота смены достигает 60 кадров в секунду (да, это магическое число берется отсюда), давая основному потоку только 16 мc для прорисовки всего экрана.

Продолжительность сетевого вызова может быть в тысячи раз больше.

Когда мы хотим загрузить что-либо из Интернета (прогноз погоды, пробки, сколько стоит ваша часть биткоина в данный момент), мы не должны делать это из главного потока. Более того, Android не позволит нам, выбросив NetworkOnMainThreadException.

Семь лет назад, когда я разрабатывал свои первые приложения на Android, подход от Google был ограничен использованием AsyncTasks. Давайте посмотрим, как мы писали код для общения с сервером (псевдокод преимущественно):

Метод doInBackground() гарантированно будет вызван не на основном потоке. Но на каком? Зависит от реализации. Вот как Android выбирает поток (это часть исходного кода класса AsyncTask):

Здесь можно увидеть, что выполнение зависит от параметра Executor. Посмотрим, откуда он берется:

Как здесь указано, по умолчанию executor ссылается на пул потоков размера 1. Это означает, что все AsyncTasks в вашем приложении запускаются последовательно. Это не всегда было верно, так как для версий ОС от DONUT до HONEYCOMB использовался пул размером от 2 до 4(в зависимости от количества ядер процессора). После HONEYCOMB AsyncTasks снова выполняются последовательно по умолчанию.

Итак, работа выполнена, байты закончили свое длинное путешествие с другого полушария. Нужно превратить их во что-то понятное и разместить на экране. К счастью, наша Activity тут как тут. Давайте поместим результат в одно из наших View.

О, черт! Опять исключение!

android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

Но мы не делали никаких сетевых обращений на основном потоке! Правильно, но мы попытались нарушить другой закон UI. Пользовательский интерфейс можно менять только из UI-потока. Это верно не только для Android, но и практически для любой системы, с которой вы столкнетесь. Причину этого хорошо объяснили в Java Concurrency In Practice. Вкратце – архитекторы хотели избежать сложной блокировки при изменениях из нескольких источников (пользовательский ввод, биндинг и другие изменения). Использование единственного потока решает эту проблему.

Да, но UI все равно нужно обновлять. У AsyncTask есть еще метод onPostExecute, который вызывается на UI-потоке:

Как эта магия работает? Посмотрим в исходном коде AsyncTask:

AsyncTask использует Handler для вызова onPostExecute в UI, ровно как и метод postOnUiThread в компонентах Android.

Handler прячет всю внутреннюю кухню. Какую именно? Идея состоит в том, чтобы иметь бесконечный цикл проверки сообщений, приходящих на UI-поток, и обрабатывать их соответствующе. Велосипедов тут никто не изобретает, хотя без кручения педалей не обошлось.

image loader

Для Android это реализовано классом Looper, который передается в InternalHandler в приведенном выше коде. Суть класса Looper находится в методе loop:

Он просто опрашивает очередь входящих сообщений в бесконечном цикле и обрабатывает эти сообщения. Это означает, что на UI-потоке должен быть инициализированный экземпляр Looper. Можно получить доступ к нему с помощью статического метода:

Кстати, вы только что узнали, как проверить, вызывается ли ваш код в UI-потоке:

Если вы попытаетесь создать экземпляр Handler в методе doInBackground, то получите другое исключение. Оно сообщит о необходимости наличия Looper для потока. Теперь вы знаете, что это значит.

Надо заметить, что AsyncTask может быть создан только в UI-потоке по указанным выше причинам.
Вы можете подумать, что AsyncTask – это удобный способ выполнения фоновой работы, так как он скрывает сложность и требует немного усилий при использовании, но есть несколько проблем, которые приходится решать по пути:

В следующей части я подробно разберу эти проблемы и покажу, как Loaders могут помочь их решить.

Источник

Потоки

Потоки позволяют выполнять несколько задач одновременно, не мешая друг другу, что даёт возможность эффективно использовать системные ресурсы. Потоки используются в тех случаях, когда одно долгоиграющее действие не должно мешать другим действиям. Например, у нас есть музыкальный проигрыватель с кнопками воспроизведения и паузы. Если вы нажимаете кнопку воспроизведения и у вас запускается музыкальный файл в отдельном потоке, то вы не можете нажать на кнопку паузы, пока файл не воспроизведётся полностью. С помощью потоков вы можете обойти данное ограничение.

Использование фоновых потоков

Чтобы быть уверенным, что ваше приложение не теряет отзывчивости, хорошим решением станет перемещение всех медленных, трудоёмких операций из главного потока приложения в дочерний.

Применение фоновых потоков — необходимое условие, если вы хотите избежать появления диалогового окна для принудительного закрытия приложения. Когда активность в Android на протяжении 5 секунд не отвечает на события пользовательского ввода (например, нажатие кнопки) или приёмник широковещательных намерений не завершает работу обработчика onReceive() в течение 10 секунд, считается, что приложение зависло. Подобные ситуации следует избегать любой ценой. Используйте фоновые потоки для всех трудоёмких операций, включая работу с файлами, сетевые запросы, транзакции в базах данных и сложные вычисления.

Android предоставляет несколько механизмов перемещения функциональности в фоновый режим.

Класс AsyncTask позволяет определить операции, которые будут выполняться в фоне, вы также будете иметь доступ к обработчику событий, что позволит отслеживать прогресс выполнения задач и выводить результаты в контексте главного графического потока. Подробнее об этом классе в отдельной статье.

Хотя использование AsyncTask — хорошее решение, случается, что для работы в фоновом режиме приходится создавать собственные потоки и управлять ими.

В Java есть стандартный класс Thread, который вы можете использовать следующим образом:

Данный способ подходит только для операций, связанных с временем. Но вы не сможете обновлять графический интерфейс программы.

Если вам нужно обновлять интерфейс программы, то нужно использовать AsyncTask, о котором говорилось выше, или вы можете реализовать ваш собственный класс, наследованный от Thread, используя объект Handler из пакета android.os для синхронизации с потоком GUI перед обновлением пользовательского интерфейса.

Вы можете создавать дочерние потоки и управлять ими с помощью класса Handler, а также классов, доступных в пространстве имён java.lang.Thread. Ниже показан простой каркас для переноса операций в дочерний поток.

Плохое приложение

Для имитации тяжёлой работы программа делает паузу на двадцать секунд, а потом выводит текст с подсчётом котов. Если нажать на кнопку один раз и подождать двадцать секунд, то программа отработает как положено. Но представьте себе, что вы нажали на кнопку один раз. Программа запустила паузу. Вы, не дожидаясь окончания паузы, снова нажали на кнопку. Программа должна выполнить вашу команду, но предыдущая команда ещё не отработала и наступает конфликт. Попробуйте нажать на кнопку несколько раз с небольшими перерывами. В какой-то момент приложение зависнет и выведет системное диалоговое окно:

thread2

В реальных приложениях такое окно может разозлить пользователя и он поставит низкую оценку вашему приложению.

В данном случае ошибку вызывает не сам вывод текста в текстовой метке, который, к слову, тоже выполняется в основном потоке, а сам щелчок кнопки. Если вы закомментируете последние две строчки кода, связанные с TextView, то ошибка сохранится.

Вам необходимо перенести трудоёмкую задачу в отдельный поток. Для этого создаётся экземпляр класса Runnable, у которого есть метод run(). Далее создаётся объект Thread, в конструкторе у которого указывается созданный Runnable. После этого можно запускать новый поток с помощью метода start(). Перепишем пример.

Весь код мы перенесли в метод run(). Теперь вы можете безостановочно щёлкать по кнопке. На этот раз приложение сохранит свою работоспособность. Чтобы в этом убедиться, в код добавлено протоколирование логов Log.i(). При каждом нажатии создаётся новый поток, в котором выполняется код. Потоки друг другу не мешают и дожидаются своей очереди, когда система позволит им отработать.

Основной поток также называют UI-потоком. Имено в главном потоке можно обновить текст у текстовой метки. В создаваемых нами потоках это делать нельзя. Если вы уберёте комментарии с последнего примера и запустите проект, то получите сообщение об ошибке.

Нужен некий посредник между создаваемыми потоками и основным UI-потоком. В роли такого посредника служит класс Handler (полное название класса android.os.Handler, не перепутайте). Вам нужно создать экземпляр класса и указать код, который нужно выполнить.

После строчки кода с Log.i() добавьте вызов метода посредника.

Поток вызывает посредника, который в свою очередь обновляет интерфейс. В нашем случае посредник посылает пустое сообщение от потока.

Но бывает так, что от потока требуется получить информацию для обработки. Ниже упрощённый пример.

Запуск потока

Предположим, мы разрабатываем собственный проигрыватель. У нас есть кнопка Play, которая вызывает метод play() для воспроизведения музыки:

Теперь запустим метод в другом потоке. Сначала создаётся новый поток. Далее описывается объект Runnable в конструкторе потока. А внутри созданного потока вызываем наш метод play(). И, наконец, запускаем поток.

Усыпить поток

Иногда требуется временно приостановить поток («усыпить»):

Приоритет потоков

Для установки приоритета процесса используется метод setPriority(), который вызывается до запуска потока. Значение приоритета может варьироваться от Thread.MIN_PRIORITY (1) до Thread.MAX_PRIORITY (10):

Отмена выполнения потока

У потока есть метод stop(), но использовать его не рекомендуется, поскольку он оставляет приложение в неопределённом состоянии. Обычно используют такой подход:

Существует и другой способ, когда все запускаемые потоки объявляются демонами. В этом случае все запущенные потоки будут автоматически завершены при завершении основного потока приложения:

Источник

Android programmers blog

Simply about difficult

Поиск по этому блогу

понедельник, 3 декабря 2012 г.

Выполнение задач в фоновом режиме в Android

Часто у людей пишущих программное обеспечение возникает задача сделать ту или иную задачу в фоне или отделить её от общего потока, пусть то будет проигрывание музыки в фоне, или допустим выполнение GET/POST запроса на сервер когда программа находится в спящем режиме, ну или например запустить какой-то не большой модуль в отдельном потоке для того что бы не загружать сильно программу разным сложным функционалом и что бы она не тормозила. Для таких задач есть такие прекрасные классы как Runnable, Thread, AsyncTask и Service. Сегодня я хочу вам рассказать про использование этих классов, с некоторыми вы сталкивались уже, я описывал класс Service в туториале про написание игры, в 8 уроке. Сегодня же мы рассмотрим все варианты работе с потоками и фоновыми режимами.
Для начала давайте я расскажу что такое каждый из данных классов.

Описание

Runnable — интерфейс предназначен для обеспечения общего протокола для объектов, которые вы хотите выполнять, пока они активны. Например, Runnable реализуется класс Thread. Будучи активным просто означает, что поток было запущено и еще не было остановлено. В общем это интерфейс реализующий фоновое воспроизведение ваших аппелептов единожды.

Thread — поток выполнения фонового элемента в программе. Виртуальная машина Java позволяет приложениям иметь несколько потоков выполнения, работающих одновременно. Например как и в случае с runnable запустить отдельный кусок программы что бы он обрабатывал какие-то функции в фоне не мешаю основному потоку.

AsyncTask — отдельный класс для выделения функций разного типа в отдельный поток, его цель – это выполнение тяжелых задач и передача в UI-поток результатов работы. Но при этом нам не надо задумываться о создании Handler и нового потока.

Service — это компонент приложения, который позволяет приложению осуществлять те или иные длящиеся операции без взаимодействия с пользователем напрямую или позволяющий осуществлять взаимодействие с другими приложениями. Каждый сервис должен быть объявлен в AndroidManifest.xml с тегом «service». Сервисы могут быть запущены командами Context.startService() и Context.bindService().

Примеры

Runnable

Теперь давайте рассмотрим все с более углубленно каждый класс по отдельности, начнем мы скорей всего с класс Runnable. Он довольно прост и его можно использовать прямо в коде не создавая отдельный классов и не загромождая код. Он имеет один единственный метод который называется run(), собственно в нем и происходит все невиданное и желанное. Например вам нужно что бы функция отправляла запрос на сервер, но при этом у вас программа выполняет туеву хучу разных функций, и этот метод который отправляет запрос просто тормозит весь процесс. Тогда решением будет являться выделить в отдельный поток эту функцию и просто вызывать её там.

Вот как бы это сделал я используя класс runnable:

Тут все просто, мы создаем объект типа хендлер для привязки к потоку, дальше создаем сам потом в котором запускаем наш интерфейс, а внутри интерфейса запускаем наш метод run() в котором будет происходить выполнение метода отправки запроса на сервер. Все это можно вписывать прямо внутри метода onCreate(), так как это не является методом, а является прямым созданием и обращением к классу и интерфейсу класса Thread.

Использовать такое конечно же не сильно одобряется, но есть случаи когда создать сервис или асинкТаск вам не нужно так как оно ничего возвращать вам не будет, можно использовать такую простую конструкцию. Надеюсь ясно, так как это самое простое что может делать данный класс.

Thread

Перейдем к следующему участнику нашего шоу, это будет класс Thread, он так же прост в использовании как и интерфейс runnable, собственно я думаю что вы заметили что он используется при работе с классом runnable, но тут мы будем создавать отдельный класс в отдельном файле для работы с классом Thread, можно использовать его как и интерфейс, но лучше это делать так как я сейчас покажу.

Для начала создадим отдельный класс и назовем его например Worker, он у нас будет выполнять какую-то грязную работу, неважно какую… Дальше нам нужно унаследовать класс Thread, смотрим как это делается.

Но эту конструкцию я снова не поддерживаю, так как она громоздкая и иногда не сильно рабочая. (: Дело в том что иногда для использования потоков достаточно сделать обычный runnable и не мучать себя разными созданиями классов, и вызовами этих классов в других классах наследниках, проще написать пару строк в текущей активности и через неё выделить нужный функционал, пример такого создания можно посмотреть выше в пункте «Runnable».

AsyncTask

Этот класс очень удобен, его можно использовать в активности создав его экземпляр прямо в самом конце класса. Он имеет в себе три метода один из которых позволяет обрабатывать нужный код в фоне, остальные два созданы для запуска диалога о загрузки и отключении диалога по окончанию. Давайте рассмотрим что это за три метода:

doInBackground – будет выполнен в новом потоке, здесь решаем все свои тяжелые задачи. Т.к. поток не основной — не имеет доступа к UI.

onPreExecute – выполняется перед doInBackground, имеет доступ к UI, он собственно и запускает диалог предупреждающий юзера об работе программы.

onPostExecute – выполняется после doInBackground (не срабатывает в случае, если AsyncTask был отменен — об этом в следующих уроках), имеет доступ к UI. Метод отключает или заканчивает уже отработанные функции и выключает диалог после завершения работы потока.

Давайте рассмотрим пример работу с этим классом.

Класс очень практичен и гибок, его бы я советовал применять во всех случаях работы с потоками, так как он удобен, с его помощью можно возвращать полученные в фоне данные, обрабатывать сложные и громоздкие функции и все это будет не заметно для пользователя. В общем как совет, почитайте об этом классе побольше, если не поняли из моего примера, и используйте исключительно его. Правда если функционал не сильно сложный можно использовать Runnable, как я писал выше. Но это дело ваше (: Идем дальше…

Service

Тут я думаю все с ним работали если читали мои статьи по написанию игры, но я повторюсь и снова расскажу об этом классе.

Класс хорош для написания простых функций, как на пример для написания музыкального плеера ифункции воспроизведение звука в фоне, когда вы свернули свою программу, а музыка все так же играет, это называется многопоточность. Для примера я вам снова приведу код из игры в котором музыка играет в фоне приложения, и для того что бы остановить или запустить сервис, нужно создать intent который посылает метод в сервис и дает ему понять что ему делать, запустить его или приостановить.

Сервис создается в отдельном классе как и Thread, и запускается он так же из отдельной активности из нужного вам метода. Смотрим как создается класс Service.

Далее нам нужно его зарегистрировать в AndroidManifest’e.xml как и активити, для того что бы Eclipse знал что этот класс можно запускать как сервис:

А дальше мы запускаем наш сервис из активности:

Ну и в нужном месте мы его будем останавливать, например по нажатию кнопки:

Источник

Понравилась статья? Поделить с друзьями:
Добавить комментарий
  • Как сделать успешный бизнес на ритуальных услугах
  • Выездной кейтеринг в России
  • Риски бизнеса: без чего не обойтись на пути к успеху
  • android studio фон приложения
  • android studio структура приложения