Как работать с AsyncTask в Android?

В этом уроке мы создадим пример работы с AsyncTask и немного разберем потоки в Android.

Для чего нужен AsyncTask?

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

Немного о процессах

С помощью манифест файла можно задать новый процесс компонента, каждый тег компонента (activity, service, receiver и provider) поддерживает атрибут android:process. Этот атрибут позволяет задать процесс, в котором будет выполняться компонент. В Android процессы существуют по мере важности, но как только потребуются ресурсы для новых процессов старые процессы будут вынесены из по иерархии важности.

Реализация примера AsyncTask

Шаг 1

Создаем Android приложение File->New Project->Android Module.

В layout добавляем main.xml со следующим содержимым:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent" >

    <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:text="AsyncTask"
            tools:context=".AsyncTaskActivity" />

    <ProgressBar
            android:id="@+id/progress"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/textView1"
            android:layout_marginTop="34dp" />

    <Button
            android:id="@+id/btn_start"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/progress"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="40dp"
            android:minWidth="120dp"
            android:text="Старт" />

    <TextView
            android:id="@+id/txt_percentage"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_below="@+id/progress"
            android:text="Загрузка  0%"
            android:textAppearance="?android:attr/textAppearanceMedium" />

</RelativeLayout>

Выглядит она так:

Шаг 2

Создадим новое Activity — MyActivity.

Объявим следующие переменные:

private Button btn_start;
private ProgressBar progressBar;
private TextView txt_percentage;

В переопределенный метод onCreate() добавим следующий код:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    btn_start = (Button) findViewById(R.id.btn_start);
    progressBar =  (ProgressBar) findViewById(R.id.progress);
    txt_percentage= (TextView) findViewById(R.id.txt_percentage);

    btn_start.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            //деактивируем кнопку которая запускает AsyncTask
            btn_start.setEnabled(false);

            //запускаем наш AsyncTask
            new ShowDialogAsyncTask().execute();
        }

    });
}

Шаг 3

Создаем следующий компонент, класс в котором мы и реализуем AsyncTask.

Для это нужно унаследоваться от AsyncTask:

private class ShowDialogAsyncTask extends AsyncTask<Void, Integer, Void> {

        int progress_status;

        @Override
        protected void onPreExecute() {
            // обновляем пользовательский интерфейс сразу после выполнения задачи
            super.onPreExecute();

            Toast.makeText(MyActivity.this, "Вызов onPreExecute()", Toast.LENGTH_SHORT).show();

            progress_status = 0;
            txt_percentage.setText("Загрузка 0%");

        }

        @Override
        protected Void doInBackground(Void... params) {

            while(progress_status<100){

                progress_status += 2;

                publishProgress(progress_status);
                SystemClock.sleep(300);

            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);

            progressBar.setProgress(values[0]);
            txt_percentage.setText("загрузка " +values[0]+"%");

        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            Toast.makeText(MyActivity.this, "Вызов onPostExecute()", Toast.LENGTH_SHORT).show();

            txt_percentage.setText("Загрузка завершена!");
            btn_start.setEnabled(true);
        }
    }

Разъяснение к Generic параметрам AsyncTask.

А теперь разберем, что значат эти методы:

onPreExecute() — вызывается в потоке пользовательского интерфейса, прежде чем задача будет выполнена. Этот шаг, как правило, используется для настройки задач, например, показывая прогресс-бар в пользовательском интерфейсе.

doInBackground(Params...) — вызывается в фоновом потоке сразу после onPreExecute (). Этот шаг используется для выполнения вычислений в фоновом режиме, который может занять много времени.

onProgressUpdate(Progress...) — вызывается в потоке пользовательского интерфейса после вызова publishProgress(Progress…). Этот метод используется для отображения любых форм прогресса в пользовательском интерфейсе, пока идут вычисления в фоновом режиме. Например, он может быть использован для анимации индикатор.

onPostExecute(Result) — вызывается в потоке пользовательского интерфейса после выполнения процесса вычислений в фоновом режиме. Результат вычислений передается на этот шаг в качестве параметра.

Урок создан: 23 мая 2013 | Просмотров: 89750 | Автор: Александр Барчук | Правила перепечатки


Добавить комментарий

Добавить комментарий

Ваш e-mail не будет опубликован.

Комментарии:

  • 23 мая 2013 в 23:12

    Сергей

    Спасибо Вам за статью, очень полезная

    • 24 мая 2013 в 00:08

      Александр Барчук

      Сергей, благодаря таким комментариям как ваши у меня все больше и больше желания давать вам интересный и качественный материал. Буду стараться давать больше информации :)

  • 07 июня 2013 в 10:20

    Павел

    отличная статья! хотелось бы больше, чтонибудь низкоуровневое, например создание игры пазлы)

  • 10 августа 2013 в 18:10

    Romillionaire

    Подскажите пожалуйста почему в методах onPreExecute и onPostExecute не работает publishProgress.TextView не меняется.

    • 29 августа 2013 в 16:06

      AChep

      В методах onPreExecute и onPostExecute publishProgress не имеет никакого смысла, так как они и так выполняются в главном потоке.

  • 22 марта 2014 в 20:34

    Витек

    Спасибо за отличный ресурс!
    Подправьте пожалуйста «А теперь разберем, что значЯт эти методы:» ;)

  • 09 ноября 2014 в 17:58

    justd3v

    Что значат аргументы Void… params, Integer… values, Void result?
    Зачем они нужны, если не используются? (Или явно не используются?)

  • 08 мая 2015 в 16:01

    Olly

    Спустя почти два года я прочитал эту публикацию и хочу сказать, что иллюстрация «Разъяснение к Generic параметрам AsyncTask» — это лучшее объяснение, которое я видел. Спасибо, что у автора есть талант и фантазия обучать эффективно.

    • 15 декабря 2016 в 08:59

      Серж

      На 100% согласен с Вами!