Примечание. Вся информация ниже доступна на Android-разработчиках Справочная страница AsyncTask .Заголовок Usage имеет пример.Также обратите внимание на безболезненную запись в блоге для разработчиков Android .
Взгляните на исходный код AsynTask .
Забавная запись < >
позволяет настроить асинхронную задачу.Скобки используются для помощи в реализации обобщений в Java .
Существует 3 важных части задачи, которые вы можете настроить:
- Тип передаваемых параметров - любое число, которое вы хотите
- Тип для того, что вы используете для обновления индикатора выполнения / индикатора
- Тип для того, что вы возвращаете однажды, выполненный с фоновой задачей
И помните, что любой из вышеперечисленных может быть интерфейсами .Вот как вы можете передавать несколько типов по одному и тому же вызову!
Типы этих трех вещей помещаются в угловые скобки:
<Params, Progress, Result>
Так что если вы собираетесь передать вURL
s и используйте Integers
для обновления хода выполнения и возврата логического значения, указывающего на успешность, которое вы напишите:
public MyClass extends AsyncTask<URL, Integer, Boolean> {
В этом случае, если вы загружаете, например, растровые изображения, вы будете обрабатывать то, что делаетес растровыми изображениями в фоновом режиме.Вы также можете просто вернуть HashMap из битмапов, если хотите.Также помните, что переменные-члены, которые вы используете, не ограничены, поэтому не чувствуйте себя слишком привязанными к параметрам, прогрессу и результату.
Для запуска AsyncTask создайте его экземпляр, а затем execute
последовательно или впараллельно.В исполнении вы передаете переменные.Вы можете передать более одного.
Обратите внимание, что вы не звоните doInBackground()
напрямую.Это потому, что это нарушит магию AsyncTask, а именно то, что doInBackground()
выполняется в фоновом потоке.Вызов его непосредственно как есть, заставит его работать в потоке пользовательского интерфейса.Таким образом, вместо этого вы должны использовать форму execute()
.Задача execute()
состоит в том, чтобы запустить doInBackground()
в фоновом потоке, а не в потоке пользовательского интерфейса.
Работа с нашим примером сверху.
...
myBgTask = new MyClass();
myBgTask.execute(url1, url2, url3, url4);
...
onPostExecute
будетсрабатывает, когда все задачи после выполнения завершены.
myBgTask1 = new MyClass().execute(url1, url2);
myBgTask2 = new MyClass().execute(urlThis, urlThat);
Обратите внимание, как вы можете передать несколько параметров в execute()
, который передает несколько параметров в doInBackground()
.Это происходит с помощью varargs (вы знаете, как String.format(...)
. Многие примеры показывают только извлечение первых параметров с помощью params[0]
, но вы должны убедитесь, что вы получили все параметры . Если вы передаете URL, это будет (взято из примера AsynTask, есть несколько способов сделать это):
// This method is not called directly.
// It is fired through the use of execute()
// It returns the third type in the brackets <...>
// and it is passed the first type in the brackets <...>
// and it can use the second type in the brackets <...> to track progress
protected Long doInBackground(URL... urls)
{
int count = urls.length;
long totalSize = 0;
// This will download stuff from each URL passed in
for (int i = 0; i < count; i++)
{
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
}
// This will return once when all the URLs for this AsyncTask instance
// have been downloaded
return totalSize;
}
Если вы собираетесь выполнять несколько задач bg, то вы должны учитывать, что вышеуказанные вызовы myBgTask1
и myBgTask2
будут выполняться в последовательности . Это хорошо, если один вызов зависит от другого,но если вызовы независимы - например, вы загружаете несколько изображений, и вам все равно, какие из них поступают первыми - тогда вы можете делать вызовы myBgTask1
и myBgTask2
параллельно с THREAD_POOL_EXECUTOR
:
myBgTask1 = new MyClass().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url1, url2);
myBgTask2 = new MyClass().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, urlThis, urlThat);
Примечание:
Пример
Вот пример AsyncTask, который может принимать столько типов, сколько вы хотитена одну и ту же команду execute()
. Ограничение - каждый тип долженТот же интерфейс:
public class BackgroundTask extends AsyncTask<BackgroundTodo, Void, Void>
{
public static interface BackgroundTodo
{
public void run();
}
@Override
protected Void doInBackground(BackgroundTodo... todos)
{
for (BackgroundTodo backgroundTodo : todos)
{
backgroundTodo.run();
// This logging is just for fun, to see that they really are different types
Log.d("BG_TASKS", "Bg task done on type: " + backgroundTodo.getClass().toString());
}
return null;
}
}
Теперь вы можете сделать:
new BackgroundTask().execute(this1, that1, other1);
Где каждый из этих объектов имеет свой тип!(который реализует тот же интерфейс)