在我的Activity中,我使用了一个从AsyncTask扩展的类和一个AsyncTask实例的参数。当我打电话给mInstanceOfAT.execute("")
时,一切都很好。
但是当我按下再次调用AsyncTask的更新按钮时应用程序崩溃(如果网络作业不起作用)。然后出现一个例外情况
无法执行任务:任务有 已被执行(任务可以 只执行一次)
我试过为Asyctask的实例调用cancel(true),但它也不起作用。到目前为止唯一的解决方案是创建Asyntask的新实例。这是正确的方法吗?
感谢。
答案 0 :(得分:216)
AsyncTask
个实例只能使用一次。
相反,只需将您的任务称为new MyAsyncTask().execute("");
来自AsyncTask API文档:
此类必须遵循一些线程规则才能正常工作:
答案 1 :(得分:28)
在Steve Prentice的回答中详细说明了ASyncTask发生故障的实例,但是,当您执行ASyncTask 多少次时,您可以自由地执行在线程运行时你喜欢什么...
将可执行代码放在 doInBackground()中的循环中,并使用并发锁来触发每次执行。您可以使用 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使用稍微复杂一点,并且您放弃使用 publishProgress()进行实际的进度报告。但是如果您关心内存,那么这种方法将确保在运行时只有一个ASyncTask保留在堆中。
答案 2 :(得分:2)
我有同样的问题。在我的情况下,我有一个我想在onCreate()
和onResume(
中完成的任务。所以我使我的Asynctask静态,并从中获取实例。现在我们仍然有同样的问题。
所以我在onPostExecute()中做的是:
instance = null;
请记住我在静态getInstance方法中检查我的实例不为null,否则我创建它:
if (instance == null){
instance = new Task();
}
return instance;
postExecute中的方法将清空实例并重新创建它。当然这可以在课外完成。
答案 3 :(得分:1)
我已将旋转任务设置为静态,然后帮助我在旋转更改时附加,分离并重新连接到UI线程。但是回到你的问题,我所做的是创建一个标志来查看线程是否正在运行。如果要重新启动线程,我会检查旋转任务是否正在运行,如果它是我举报警告。如果不是,我将其设为null然后创建一个新的,它将解决您看到的错误。此外,成功完成后,我将完成的旋转感知任务归零,以便它可以再次运行。
答案 4 :(得分:0)
是的,这是真的,医生说只能执行一个Asyntask。
每次你需要使用它时,你必须实例:
// 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> {
}