AsyncTask — пример создания асинхронных задач

| 14.07.2014

Если вы уже знакомы с понятием потока, то разобраться с AsyncTask в Андроид-приложениях не составит труда. AsyncTask или асинхронная задача — это кусок кода, который может представлять собой фоновую активность в отдельном потоке. AsyncTask позволяют избежать блокировки интерфейса в то время, когда система занята выполнением какой-то «тяжелой» задачи.

Рассмотрим простой пример, в котором задача такого типа будет обновлять в TextView значение — это будет цикл, на каждой итерации которого мы будем выводить на экран номер этой самой итерации (с некоторой задержкой). Получится своего рода таймер. Пока будет работать данный процесс мы попробуем вводить в поле EditText какую-то строку и обновлять по клику на кнопке введенным значением другой элемент TextView. Этим самым мы проверим блокируется ли интерфейс вычислениями или нет.

Итак, нам понадобиться создать:

- activity_main.xml
- MainActivity.java

Layout нашего приложения res/layout/activity_main.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center|top"
    android:orientation="vertical" >
 
    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="25dp"
        android:text="@string/app_name" />
 
    <TextView
        android:id="@+id/tv2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView" />
 
    <EditText
        android:id="@+id/edTxt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10" >        
    </EditText>
 
    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Изменить текст" 
        android:onClick="btnClick"/>
 
</LinearLayout>

Для кнопки добавлено свойство android:onClick, в котором задан метод-обработчик клика — btnClick(). Создадим класс активити с основной логикой, но саму асинхронную задачу с вычислениями поместим во внутренний класс — TheTask.

MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package ru.androiddocs.thetask;
 
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
 
import java.util.concurrent.TimeUnit;
 
 
public class MainActivity extends ActionBarActivity {
 
    private static final String LOG_TAG = "my_tag";
 
    TextView mTv, mTvChange;
    EditText mEdTxt;	
    String mResult;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mEdTxt = (EditText) findViewById(R.id.edTxt);
        mTvChange = (TextView) findViewById(R.id.tv2);
 
        new TheTask().execute("Текущий результат: ");
    }
 
    public void btnClick(View v) {		
        mTvChange.setText(mEdTxt.getText().toString());
    }
 
    class TheTask extends AsyncTask<String, Integer, String> {
 
 
        @Override
        protected void onPreExecute() {
            super.onPreExecute();  
            mTv = (TextView) findViewById(R.id.tv);
        }
 
        @Override
        protected String doInBackground(String... strData) {
            try {
                for (int i = 0; i < 60; i++) {					
                    mResult = strData[0] + i;
                    publishProgress(i);
                    TimeUnit.SECONDS.sleep(3);
                }				
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
 
            return mResult;		     
        }
 
        @Override
        protected void onProgressUpdate(Integer... currInt) {
            super.onProgressUpdate(currInt);
            mTv.setText("" + currInt[0]);
        }
 
        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
 
            Log.d(LOG_TAG, result);
        }
    }
}

В методе onCreate() мы получаем доступ до нужных элементов View и запускаем асинхронную задачу, передавая ей в качестве параметра строку (мы ее будем использовать при обновлении процессом TextView:

1
new TheTask().execute("Текущий результат: ");

Сам класс TheTask наследуется от класса AsyncTask. Используется три параметра:

1
<String, Integer, String>.

Первый — это передаваемый в класс параметр (если передаете число, то нужно изменить, например, на Integer). Второй параметр типа Integer используется для промежуточных результатов при вызове метода onProgressUpdate() и третий типа String используется для финального результата (возвращаемого значения).

Суть методов:

- onPreExecute() — срабатывает перед запуском задачи
- doInBackground() — непосредственно сама асинхронная задача (фоновая работа)
- onProgressUpdate() — метод, вызываемый в процесс работы задачи. Используется для обновления прогресса выполнения
- onPostExecute() — метод, срабатывающий в самом конце задачи, и получает итоговый результат

Вызов метода onProgressUpdate() делается с помощью publishProgress(), где с параметром мы передаем номер итерации (как вы помните, для промежуточных результатов мы можем использовать только целые числа — Integer). Полученное число выводим в TextView.

AsyncTask - пример создания асинхронных задач

В заключительном методе onPostExecute() выводим в логи итоговый результат. По сути, это объединение строки «Текущий результат: » и номера последней итерации.

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

AsyncTask - пример создания асинхронных задач

Если, например, вы не используете «промежуточный» метод onProgressUpdate(), то определение класса TheTask может быть таким:

1
class TheTask extends AsyncTask<String, Void, String>

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

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*