多次执行 AsyncTask

在我的 Activity 中,我使用了一个从 AsyncTask 扩展的类和一个参数,它是 AsyncTask 的一个实例。当我调用 mInstanceOfAT.execute("")时,一切都很好。 但是当我按下一个更新按钮再次调用 AsyncTask 时,应用程序崩溃了(如果网络作业不工作)。然后出现一个例外,它说

无法执行任务: 任务已 已经执行(任务可以是 只执行一次)

我已经尝试调用取消(真)的实例的 Asyctask,但它也不工作。到目前为止,唯一的解决方案是创建 Asyntask 的新实例。这样对吗?

谢谢。

96992 次浏览

AsyncTask实例只能使用一次。

相反,只需像 new MyAsyncTask().execute("");那样调用您的任务

来自 AsyncTask API 文档:

穿线规则

要使这个类正常工作,必须遵循以下几条线程规则:

  • 任务实例必须在 UI 线程上创建。
  • 必须在 UI 线程上调用 execute (Params...)。
  • 不要手动调用 onPreExecute ()、 onPostExecute (Result)、 doInBack (Params...)、 onProgressUpdate (Progress...)。
  • 任务只能执行一次(如果尝试第二次执行,将引发异常)

在 Steve Prentice 的回答中,我们已经详细说明了为什么 ASyncTask 的实例会被忽略——然而,当你在 多少次上被限制执行 ASyncTask 的时候,你可以在线程运行的时候自由地做你想做的事情。

将可执行代码放入 背景()中的一个循环中,并使用一个并发锁来触发每次执行。您可以使用 PublishProgress ()/onProgressUpdate ()检索结果。

例如:

class GetDataFromServerTask extends AsyncTask<Input, Result, Void> {


private final ReentrantLock lock = new ReentrantLock();
private final Condition tryAgain = lock.newCondition();
private volatile boolean finished = false;


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


lock.lockInterruptibly();


do {
// This is the bulk of our task, request the data, and put in "result"
Result result = ....


// Return it to the activity thread using publishProgress()
publishProgress(result);


// At the end, we acquire a lock that will delay
// the next execution until runAgain() is called..
tryAgain.await();


} while(!finished);


lock.unlock();
}


@Override
protected void onProgressUpdate(Result... result)
{
// Treat this like onPostExecute(), do something with result


// This is an example...
if (result != whatWeWant && userWantsToTryAgain()) {
runAgain();
}
}


public void runAgain() {
// Call this to request data from the server again
tryAgain.signal();
}


public void terminateTask() {
// The task will only finish when we call this method
finished = true;
lock.unlock();
}


@Override
protected void onCancelled() {
// Make sure we clean up if the task is killed
terminateTask();
}
}

当然,这比传统的 ASyncTask 用法稍微复杂一些,而且您放弃了使用 公布进度()来进行实际的进度报告。但是如果您关心的是内存,那么这种方法将确保在运行时堆中只保留一个 ASyncTask。

我将我的旋转任务设置为静态的,这有助于我在旋转更改时将它们附加、分离和重新附加到 UI 线程。但是回到你的问题,我要做的是创建一个标志来检查线程是否正在运行。当您想要重新启动线程时,我会检查旋转任务是否正在运行,如果正在运行,我会吐司一个警告。如果不是,我将它设置为 null,然后创建一个新的,它将解决您看到的错误。此外,在成功完成后,我取消了已完成的轮换感知任务,以便它可以再次执行。

是的,这是真的,医生说只能执行一个异步任务。

每次你需要使用它,你必须实例:

// Any time if you need to call her
final FirmwareDownload fDownload = new FirmwareDownload();
fDownload.execute("your parameter");


static class FirmwareDownload extends AsyncTask<String, String, String> {
}

我也有同样的问题。在我的情况下,我有一个任务,我想在 onCreate()onResume()。因此,我将 Asynctask 设置为静态,并从中获取实例。现在我们还有同样的问题。

所以我在 onPostExecute ()中所做的是:

instance = null;

请记住,我在静态 getInstance 方法中检查我的实例不是 null,否则我创建它:

if (instance == null){
instance = new Task();
}
return instance;

PostExecute 中的方法将清空实例并重新创建它。