- What to Use for Background Processing in Android?
- Here’s an Example
- What Exactly is Background Work?
- Categories of Background Tasks
- Introduction to background processing in Android — Tutorial
- 1. Background processing in Android
- 1.1. Why using concurrency?
- 1.2. Main thread
- 1.3. Threading in Android
- 2. Handler
- 2.1. Purpose of the Handler class
- 2.2. Creating and reusing instances of Handlers
- 2.3. Example
- 3. AsyncTask
- 3.1. Parallel execution of several AsyncTasks
- 3.2. Example: AsyncTask
- 4. Background processing and lifecycle handling
- 4.1. Retaining state during configuration changes
- 4.2. Using the application object to store objects
- 5. Headless Fragments and background processing
- Руководство по фоновой работе в Android. Часть 1
- Основы UI
What to Use for Background Processing in Android?
By default, application code runs within the main thread. Every statement is therefore executed in sequence. If you perform an extended-lasting operation, the appliance blocks until the corresponding operation has finished. To provide an honest user experience all potentially slow running operations in an Android application should run asynchronously. this will be archived via concurrency constructs of the Java language or of the Android framework. Potentially slow operations are for instance: network, file, and database access, and sophisticated calculations and tasks like them need background processing, let’s dive a little deeper and look at that in detail!
Android modifies the interface and handles input events from one single thread, called the most thread. Android collects all events during this thread during a queue and processes this queue with an instance of the Looper class. The Android Operating System uses the Thread class to perform asynchronous tasks like the ones mentioned above the header image. The java.util.concurrent is also provided by it to perform certain tasks, something which we call background. For instance, by using the ThreadPools and Executor classes.
Attention reader! Don’t stop learning now. Get hold of all the important Java Foundation and Collections concepts with the Fundamentals of Java and Java Collections Course at a student-friendly price and become industry ready. To complete your preparation from learning a language to DS Algo and many more, please refer Complete Interview Preparation Course.
If you would like to update the interface from a replacement Thread, you would like to synchronize with the most thread. due to these restrictions, Android developers typically use Android-specific code constructs.
Here’s an Example
The RxJava open-source framework allows specifying an observer of an observable stream of knowledge. Once the events happen and are reported finished, the observer is named by the framework. you’ll configure during which thread the observer and observable run.
What Exactly is Background Work?
An app is taken into account to be running within the background as long as each of the subsequent conditions is satisfied:
A simple glyph to understand this process could be taken from the below Image:
fig.1
Categories of Background Tasks
Background tasks fall under one among the subsequent main categories:
- Immediate
- Deferred
- Exact
To categorize a task, answer the subsequent questions, and traverse the corresponding decision tree in (fig 1:)
- Does the task complete itself when the user was/is interacting with the application? Yes? then should this be classified for immediate exec? If not, proceed to the second question.
- Does the task get to run at a particular time? If you are doing got to run a task at a particular time, categorize the task as exact.
Most tasks don’t get to be run at a particular time. Tasks generally leave slight variations in once they run that are supported conditions like network availability and remaining battery.
- Tasks that do not get to be run at a particular time should be categorized as deferred.
These tasks could be used for background processing in Android, Let’s learn more about them in detail:
1. Immediate tasks
For tasks that ought to be executed immediately and wish continued processing, albeit the user puts the appliance in the background or the device restarts, we recommend using WorkManager and its support for long-running tasks. In specific cases, like with media playback or active navigation, you would possibly want to use foreground services directly.
2. Deferred tasks
Every task that’s indirectly connected to user interaction and may run at any time within the future is often deferred. The recommended solution for deferred tasks is WorkManager. The WorkManager makes it quite efficient and easy to schedule the asynchronous and deferrable tasks, even the tasks which need to resume when the phone restarts!
3. Exact tasks
A task that must be executed at a particular point in time and they can use AlarmManager.
Источник
Introduction to background processing in Android — Tutorial
This tutorial introduces the concept of asynchronous processing in Android applications.
1. Background processing in Android
1.1. Why using concurrency?
By default, application code runs in the main thread. Every statement is therefore executed in sequence. If you perform a long lasting operation, the application blocks until the corresponding operation has finished.
To provide a good user experience all potentially slow running operations in an Android application should run asynchronously. This can be archived via concurrency constructs of the Java language or of the Android framework. Potentially slow operations are for example network, file and database access and complex calculations.
Android enforces a worst case reaction time of applications. If an activity does not react within 5 seconds to user input, the Android system displays an Application not responding (ANR) dialog. From this dialog the user can choose to stop the application. |
1.2. Main thread
Android modifies the user interface and handles input events from one single thread, called the main thread. Android collects all events in this thread in a queue and processes this queue with an instance of the Looper class.
1.3. Threading in Android
Android supports the usage of the Thread class to perform asynchronous processing. Android also supplies the java.util.concurrent package to perform something in the background. For example, by using the ThreadPools and Executor classes.
If you need to update the user interface from a new Thread , you need to synchronize with the main thread. Because of this restrictions, Android developer typically use Android specific code constructs.
Standard Android provides the android.os.Handler class or the AsyncTasks classes. More sophisticated approaches are based on open source solutions which are using callbacks.
For example, the RxJava open source framework allow to specify an observer of an observable stream of data. Once the events happen the observer is called by the framework. You can configure in which thread the observer and observable run.
2. Handler
2.1. Purpose of the Handler class
A Handler object registers itself with the thread in which it is created. It provides a channel to send data to this thread, for example the main thread. The data which can be posted via the Handler class can be an instance of the Message or the Runnable class. A Handler is particular useful if you have want to post multiple times data to the main thread.
2.2. Creating and reusing instances of Handlers
To implement a handler subclass it and override the handleMessage() method to process messages. You can post messages to it via the sendMessage(Message) or via the sendEmptyMessage() method. Use the post() method to send a Runnable to it.
To avoid object creation, you can also reuse the existing Handler object of your activity.
The View class allows you to post objects of type Runnable via the post() method.
2.3. Example
The following code demonstrates the usage of an handler from a view. Assume your activity uses the following layout.
With the following code the ProgressBar get updated once the users presses the Button .
3. AsyncTask
The AsyncTask class allows to run instructions in the background and to synchronize again with the main thread. It also reporting progress of the running tasks. AsyncTasks should be used for short background operations which need to update the user interface.
To use AsyncTask you must subclass it. The parameters are the following AsyncTask .
An AsyncTask is started via the execute() method. This execute() method calls the doInBackground() and the onPostExecute() method.
TypeOfVarArgParams is passed into the doInBackground() method as input. ProgressValue is used for progress information and ResultValue must be returned from doInBackground() method. This parameter is passed to onPostExecute() as a parameter.
The doInBackground() method contains the coding instruction which should be performed in a background thread. This method runs automatically in a separate Thread .
The onPostExecute() method synchronizes itself again with the user interface thread and allows it to be updated. This method is called by the framework once the doInBackground() method finishes.
3.1. Parallel execution of several AsyncTasks
By default, AsyncTask tasks are executed sequence (for Android versions higher than Android 3.0). To run AsyncTasks in sequence use the executeOnExecutor() method specifying AsyncTask.THREAD_POOL_EXECUTOR as first parameter.
3.2. Example: AsyncTask
The following code demonstrates how to use the AsyncTask to download something from the Internet. The code requires the android.permission.INTERNET permission in your Android manifest.
4. Background processing and lifecycle handling
4.1. Retaining state during configuration changes
One challenge in using threads is to consider the lifecycle of the application. The Android system may kill your activity or trigger a configuration change which will also restart your activity.
You also need to handle open dialogs, as dialogs are always connected to the activity which created them. In case the activity gets restarted and you access an existing dialog you receive a View not attached to window manager exception.
4.2. Using the application object to store objects
You can implement an Application class for your Android application.
To use your application class assign the classname to the android:name attribute of your application.
The application class is automatically created by the Android runtime and is available unless the whole application process is terminated.
This class can be used to access objects which should be cross activities or available for the whole application lifecycle. In the onCreate() method you can create objects and make them available via public fields or getter methods.
The onTerminate() method in the application class is only used for testing. If Android terminates the process in which your application is running all allocated resources are automatically released.
You can access the Application via the getApplication() method in your activity.
5. Headless Fragments and background processing
Fragments which do return null in the onCreateView methods are called headless fragments, as the provide no views. Headless fragments can retain there fields between configuration changes via the setRetainInstance(true) method call.
For example, if you define an AsyncTask as field in a headless fragment, it can continue to run during configuration changs.
Источник
Руководство по фоновой работе в Android. Часть 1
О фоновой работе приложений в Android есть много статей, но мне не удалось найти подробного руководства по реализации работы в фоне – думаю, из-за того, что появляется все больше новых инструментов для такой работы. Поэтому я решил написать серию статей о принципах, инструментах и методах асинхронной работы в приложениях под Android.
Будет несколько частей:
- Основной поток, осуществление фоновой работы с помощью AsyncTask, публикация результатов в основном потоке.
- Затруднения при использовании AsyncTask. Loaders как один из способов их избежать.
- Работа в фоне с помощью ThreadPools и EventBus.
- RxJava 2 как метод асинхронной работы.
- Корутины в Kotlin как метод асинхронной работы.
Начнем с первой части.
Основы 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-поток, и обрабатывать их соответствующе. Велосипедов тут никто не изобретает, хотя без кручения педалей не обошлось.
Для Android это реализовано классом Looper, который передается в InternalHandler в приведенном выше коде. Суть класса Looper находится в методе loop:
Он просто опрашивает очередь входящих сообщений в бесконечном цикле и обрабатывает эти сообщения. Это означает, что на UI-потоке должен быть инициализированный экземпляр Looper. Можно получить доступ к нему с помощью статического метода:
Кстати, вы только что узнали, как проверить, вызывается ли ваш код в UI-потоке:
Если вы попытаетесь создать экземпляр Handler в методе doInBackground, то получите другое исключение. Оно сообщит о необходимости наличия Looper для потока. Теперь вы знаете, что это значит.
Надо заметить, что AsyncTask может быть создан только в UI-потоке по указанным выше причинам.
Вы можете подумать, что AsyncTask – это удобный способ выполнения фоновой работы, так как он скрывает сложность и требует немного усилий при использовании, но есть несколько проблем, которые приходится решать по пути:
- Каждый раз нужно писать достаточно много кода для решения относительно простой задачи
- AsyncTasks ничего не знают о жизненном цикле. При неправильном обращении лучшее, что вы получите — утечка памяти, в худшем – сбой
- AsyncTask не поддерживает сохранение состояния прогресса и повторное использование результатов загрузки.
В следующей части я подробно разберу эти проблемы и покажу, как Loaders могут помочь их решить.
Источник