我没有花太多时间在Android上使用AsyncTasks
。我试图了解如何将变量传入和传递给类。语法:
class MyTask extends AsyncTask<String, Void, Bitmap>{
// Your Async code will be here
}
它与类定义末尾的< >
语法有点混淆。以前从未见过这种语法。似乎我只限于将一个值传递给AsyncTask
。假设这个我不正确吗?如果我有更多要通过,我该怎么做?
另外,如何从AsyncTask返回值?
这是一个类,当你想使用它时,你调用new MyTask().execute()
,但你在课堂上使用的实际方法是doInBackground()
。那你在哪里实际归还的东西呢?
注意:以下所有信息均可在Android开发者AsyncTask reference page上获得。 Usage标头有一个例子。还可以看看Painless Threading Android Developers Blog Entry。
看看the source code for AsynTask。
有趣的< >
表示法允许您自定义您的异步任务。括号用于帮助实现generics in Java。
您可以自定义任务的3个重要部分:
请记住,上述任何一个都可能是接口。这是你在同一个电话上传递多种类型的方法!
您将这三种类型的东西放在尖括号中:
<Params, Progress, Result>
因此,如果你打算传入URL
s并使用Integers
更新进度并返回一个表示成功的布尔值,你会写:
public MyClass extends AsyncTask<URL, Integer, Boolean> {
在这种情况下,如果您正在下载位图,例如,您将在后台处理您对位图的处理。如果需要,您也可以返回位图的HashMap。还要记住你使用的成员变量不受限制,因此不要被params,进度和结果所束缚。
要启动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);
每个对象都是不同的类型! (实现相同的接口)
我知道这是一个迟到的答案,但这是我最后一直在做的事情。
当我需要将一堆数据传递给AsyncTask时,我可以创建自己的类,传入它然后访问它的属性,如下所示:
public class MyAsyncTask extends AsyncTask<MyClass, Void, Boolean> {
@Override
protected Boolean doInBackground(MyClass... params) {
// Do blah blah with param1 and param2
MyClass myClass = params[0];
String param1 = myClass.getParam1();
String param2 = myClass.getParam2();
return null;
}
}
然后像这样访问它:
AsyncTask asyncTask = new MyAsyncTask().execute(new MyClass());
或者我可以在我的AsyncTask类中添加一个构造函数,如下所示:
public class MyAsyncTask extends AsyncTask<Void, Void, Boolean> {
private String param1;
private String param2;
public MyAsyncTask(String param1, String param2) {
this.param1 = param1;
this.param2 = param2;
}
@Override
protected Boolean doInBackground(Void... params) {
// Do blah blah with param1 and param2
return null;
}
}
然后像这样访问它:
AsyncTask asyncTask = new MyAsyncTask("String1", "String2").execute();
希望这可以帮助!
由于您可以在方括号中传递对象数组,因此这是根据您要在后台进行处理的数据传递的最佳方式。
您可以在构造函数中传递活动或视图的引用,并使用它将数据传递回您的活动
class DownloadFilesTask extends AsyncTask<URL, Integer, List> {
private static final String TAG = null;
private MainActivity mActivity;
public DownloadFilesTask(MainActivity activity) {
mActivity = activity;
mActivity.setProgressBarIndeterminateVisibility(true);
}
protected List doInBackground(URL... url) {
List output = Downloader.downloadFile(url[0]);
return output;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
private void setProgressPercent(final Integer integer) {
mActivity.setProgress(100*integer);
}
protected void onPostExecute(List output) {
mActivity.mDetailsFragment.setDataList((ArrayList<Item>) output);
//you could do other processing here
}
}
或者,您可以使用常规线程和usea处理程序通过重写handlemessage函数将数据发送回ui线程。
传递一个简单的字符串:
public static void someMethod{
String [] variableString= {"hello"};
new MyTask().execute(variableString);
}
static class MyTask extends AsyncTask<String, Integer, String> {
// This is run in a background thread
@Override
protected String doInBackground(String... params) {
// get the string from params, which is an array
final String variableString = params[0];
Log.e("BACKGROUND", "authtoken: " + variableString);
return null;
}
}