Класс AsyncTask

Последнее обновление: 26.02.2017

В прошлых статьях был описан общий подход, который применяется сейчас для запуска в приложении нового потока и обновления в нем пользовательского интерфейса. Рассмотрим другой подход, который представляет класс AsyncTask. Хотя примение AsyncTask в современных приложениях Android устарел. Тем не менее, поскольку он по прежнему широко применяется, также рассмотрим его.

Чтобы использовать AsyncTask, нам надо:

  1. Создать класс, производный от AsyncTask (как правило, для этого создается внутренний класс в activity или во фрагменте)

  2. Переопределить один или несколько методов AsyncTask для выполнения некоторой работы в фоновом режиме

  3. При необходимости создать объект AsyncTask и вызывать его метод execute() для начала работы

Итак, создадим простейшее приложение с использованием AsyncTask. Определим следующую разметку интерфейса в файле activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="16dp"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="22sp"
            android:id="@+id/clicksView"
            android:text="Clicks: 0"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/clicksBtn"
            android:text="Click" />
    </LinearLayout>

    <Button
        android:id="@+id/progressBtn"
        android:text="Запуск"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/statusView"
        android:text="Статус"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <ProgressBar
        android:id="@+id/indicator"
        style="@android:style/Widget.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:progress="0" />
</LinearLayout>

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

Далее определим в классе MainActivity следующий код:

import android.os.AsyncTask;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    int[] integers=null;
    int clicks = 0;
    ProgressBar indicatorBar;
    TextView statusView;
    TextView clicksView;
    Button progressBtn;
    Button clicksBtn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        integers = new int[100];
        for(int i=0;i<100;i++) {
            integers[i] = i + 1;
        }
        indicatorBar = (ProgressBar) findViewById(R.id.indicator);
        statusView = findViewById(R.id.statusView);
        progressBtn = findViewById(R.id.progressBtn);
        progressBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                new ProgressTask().execute();
            }
        });

        clicksView = findViewById(R.id.clicksView);
        clicksBtn = findViewById(R.id.clicksBtn);
        clicksBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                clicks++;
                clicksView.setText("Clicks: " + clicks);
            }
        });
    }

    class ProgressTask extends AsyncTask<Void, Integer, Void> {
        @Override
        protected Void doInBackground(Void... unused) {
            for (int i = 0; i<integers.length;i++) {

                publishProgress(i);
                SystemClock.sleep(400);
            }
            return(null);
        }
        @Override
        protected void onProgressUpdate(Integer... items) {
            indicatorBar.setProgress(items[0]+1);
            statusView.setText("Статус: " + String.valueOf(items[0]+1));
        }
        @Override
        protected void onPostExecute(Void unused) {
            Toast.makeText(getApplicationContext(), "Задача завершена", Toast.LENGTH_SHORT)
                    .show();
        }
    }
}

Класс задачи ProgressTask определен как внутренний класс. Он наследуется не просто от AsyncTask, а от его типизированной версии AsyncTask<Void, Integer, Void>. Она типизируется тремя типами:

  • Класс для хранения информации, которая нужна для обработки задачи

  • Тип объектов, которые используются для индикации процесса выполнения задачи

  • Тип результата задачи

Эти типы могут быть представлены разными классами. В данном случае сущность задачи будет состоять в переборе массива integers, представляющего набор элементов Integer. И здесь нам не надо передавать в задачу никакой объект, поэтому первый тип идет как Void.

Для индикации перебора используются целые числа, которые показывают, какой объект из массива мы в данный момент перебираем. Поэтому в качестве второго типа используется Integer.

В качестве третьего типа используется опять Void, поскольку в данном случае не надо ничего возвращать из задачи.

AsyncTask содержит четыре метода, которые можно переопределить:

  • Метод doInBackground(): выполняется в фоновом потоке, должен возвращать определенный результат

  • Метод onPreExecute(): вызывается из главного потока перед запуском метода doInBackground()

  • Метод onPostExecute(): выполняется из главного потока после завершения работы метода doInBackground()

  • Метод onProgressUpdate(): позволяет сигнализировать пользователю о выполнении фонового потока

Так как метод doInBackground() не принимает ничего и не возвращает ничего, то в качестве его параметра используется Void... - массив Void, и в качестве возвращаемого типа - тоже Void. Эти типы соответствуют первому и третьему типам в AsyncTask<Void, Integer, Void>.

Метод doInBackground() перебирает массив и при каждой итерации уведомляет систему с помощью метода publishProgress(item). Так как в нашем случае для индикации используются целые числа, то параметр item должен представлять целое число.

Метод onProgressUpdate(Integer... items) получает переданное выше число и применяет его для настройки текстового поля и прогрессбара.

Метод onPostExecute() выполняется после завершения задачи и в качестве параметра принимает объект, возвращаемый методом doInBackground() - то есть в данном случае объект типа Void. Чтобы сигнализировать окончание работы, здесь выводится на экран всплывающее сообщение.

Запустим приложение. Запустим задачу, нажав на кнопку:

AsyncTask в Android

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

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850