mInstanceOfAT.execute("")
时一切正常。但是,当我按下更新按钮并再次调用AsyncTask(如果网络工作未完成时),应用程序会崩溃。此时会出现一个异常,显示:
我尝试对Asyctask的实例调用cancel(true),但它也不起作用。到目前为止唯一的解决方法是创建新的Asyntask实例。这样做是否正确?无法执行任务:任务已经被执行(一个任务只能执行一次)
谢谢。
mInstanceOfAT.execute("")
时一切正常。我尝试对Asyctask的实例调用cancel(true),但它也不起作用。到目前为止唯一的解决方法是创建新的Asyntask实例。这样做是否正确?无法执行任务:任务已经被执行(一个任务只能执行一次)
AsyncTask
实例只能使用一次。
相反,只需像这样调用你的任务:new MyAsyncTask().execute("");
来自 AsyncTask API 文档:
必须遵循该类的一些线程规则才能正常工作:
execute(Params...)
必须在 UI 线程上调用。onPreExecute()
、onPostExecute(Result)
、doInBackground(Params...)
、onProgressUpdate(Progress...)
。Steve Prentice在他的回答中详细阐述了使用ASyncTask的fire-and-forget实例的原因- 然而,虽然你在执行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存在于堆中。
runAgain
(由 onProgressUpdate
调用)中遇到了 IllegalMonitorStateException
,请参考这个答案:https://stackoverflow.com/a/42646476/2711811。它建议(并且对我有效)将 signal()
包围在 lock
/unlock
中。这可能与 publishProgress
调用 onProgressUpdate
的时间有关。 - user2711811onCreate()
和onResume()
中执行一个任务。所以我将我的Asynctask设置为静态,并从中获取实例。现在我们仍然有同样的问题。onPostExecute()
中我做了以下操作:instance = null;
记住,在静态的getInstance方法中检查实例是否为空,如果为空则创建它:
if (instance == null){
instance = new Task();
}
return instance;
postExecute方法将清空实例并重新创建。当然,这也可以在类外部完成。
我已经将我的旋转任务设置为静态,这有助于我在旋转更改时将它们附加、分离和重新附加到UI线程上。但回到你的问题,我的做法是创建一个标志来查看线程是否正在运行。当您想要重新启动线程时,我会检查旋转任务是否正在运行,如果是,我会弹出一个警告。如果不是,我将其设置为null,然后创建一个新的旋转任务,这将解决您所看到的错误。此外,在成功完成后,我会将已完成的旋转感知任务设置为null,以便再次使用。
是的,这是真的,文档中说只能执行一个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> {
}