注意:Android 开发者 AsyncTask reference page 上提供了以下所有信息。 Usage 标头有一个示例。另请查看 Painless Threading Android Developers Blog Entry。
看看the source code for AsynTask。
有趣的< > 表示法可让您自定义异步任务。括号用于帮助实现generics in Java。
您可以自定义任务的 3 个重要部分:
- 传入的参数类型 - 任意数量
- 用于更新进度条/指示器的类型
- 后台任务完成后返回的类型
请记住,以上任何一个都可能是接口。这就是你可以在同一个调用中传递多种类型的方法!
你把这三个东西的类型放在尖括号里:
<Params, Progress, Result>
因此,如果您要传入URLs 并使用Integers 更新进度并返回一个表示成功的布尔值,您可以这样写:
public MyClass extends AsyncTask<URL, Integer, Boolean> {
在这种情况下,例如,如果您正在下载位图,您将在后台处理您对位图所做的事情。如果需要,您也可以只返回位图的 HashMap。还要记住你使用的成员变量是不受限制的,所以不要被参数、进度和结果束缚。
要启动 AsyncTask 实例化它,然后execute 它可以顺序或并行进行。在执行中是您传递变量的地方。你可以传入多个。
请注意,您不要直接致电doInBackground()。这是因为这样做会破坏 AsyncTask 的魔力,即 doInBackground() 在后台线程中完成。直接按原样调用它会使其在 UI 线程中运行。因此,您应该使用execute() 的形式。 execute() 的工作是在后台线程而不是 UI 线程中启动 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]提取第一个参数,但你应该make sure you get all the params。如果你是传入 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);
其中每个对象都是不同的类型! (实现相同的接口)