多次执行AsyncTask

在我的Activity中,我使用了一个从AsyncTask扩展的类和一个参数,该参数是AsyncTask的一个实例。我打电话的时候mInstanceOfAT.execute("")一切都很好。但是当我按下再次调用AsyncTask的更新按钮时应用程序崩溃(如果网络作业不起作用)。因此出现了一个例外情况


无法执行任务:任务已经执行(任务只能执行一次)


我试过为Asyctask的实例调用cancel(true),但它也不起作用。到目前为止唯一的解决方案是创建Asyntask的新实例。这是正确的方法吗?


谢谢


呼如林
浏览 810回答 3
3回答

慕虎7371278

AsyncTask 实例只能使用一次。相反,只需将您的任务称为 new MyAsyncTask().execute("");来自AsyncTask API文档:线程规则此类必须遵循一些线程规则才能正常工作:必须在UI线程上创建任务实例。必须在UI线程上调用execute(Params ...)。不要手动调用onPreExecute(),onPostExecute(Result),doInBackground(Params ...),onProgressUpdate(Progress ...)。该任务只能执行一次(如果尝试第二次执行,则会抛出异常。)

精慕HU

在Steve Prentice的回答中详细说明了ASyncTask发生故障的实例 - 但是,当您执行ASyncTask的次数受到限制时,您可以在线程运行时自由地执行您喜欢的操作。 。将可执行代码放在doInBackground()中的循环中,并使用并发锁来触发每次执行。您可以使用publishProgress()/ onProgressUpdate()检索结果。例:class GetDataFromServerTask extends AsyncTask<Input, Result, Void> {&nbsp; &nbsp; private final ReentrantLock lock = new ReentrantLock();&nbsp; &nbsp; private final Condition tryAgain = lock.newCondition();&nbsp; &nbsp; private volatile boolean finished = false;&nbsp; &nbsp; @Override&nbsp; &nbsp; protected Void doInBackground(Input... params) {&nbsp; &nbsp; &nbsp; &nbsp; lock.lockInterruptibly();&nbsp; &nbsp; &nbsp; &nbsp; do {&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // This is the bulk of our task, request the data, and put in "result"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Result result = ....&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Return it to the activity thread using publishProgress()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; publishProgress(result);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // At the end, we acquire a lock that will delay&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // the next execution until runAgain() is called..&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tryAgain.await();&nbsp; &nbsp; &nbsp; &nbsp; } while(!finished);&nbsp; &nbsp; &nbsp; &nbsp; lock.unlock();&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; protected void onProgressUpdate(Result... result)&nbsp;&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // Treat this like onPostExecute(), do something with result&nbsp; &nbsp; &nbsp; &nbsp; // This is an example...&nbsp; &nbsp; &nbsp; &nbsp; if (result != whatWeWant && userWantsToTryAgain()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; runAgain();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; public void runAgain() {&nbsp; &nbsp; &nbsp; &nbsp; // Call this to request data from the server again&nbsp; &nbsp; &nbsp; &nbsp; tryAgain.signal();&nbsp; &nbsp; }&nbsp; &nbsp; public void terminateTask() {&nbsp; &nbsp; &nbsp; &nbsp; // The task will only finish when we call this method&nbsp; &nbsp; &nbsp; &nbsp; finished = true;&nbsp; &nbsp; &nbsp; &nbsp; lock.unlock();&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; protected void onCancelled() {&nbsp; &nbsp; &nbsp; &nbsp; // Make sure we clean up if the task is killed&nbsp; &nbsp; &nbsp; &nbsp; terminateTask();&nbsp; &nbsp; }}当然,这比传统的ASyncTask使用稍微复杂一点,并且您放弃使用publishProgress()进行实际的进度报告。但是如果你担心内存,那么这种方法将确保在运行时只有一个ASyncTask保留在堆中。

慕仙森

我遇到过同样的问题。就我而言,我有我想在做任务onCreate()和onResume()。所以我使我的Asynctask静态,并从中获取实例。现在我们仍然有同样的问题。所以我在onPostExecute()中做的是这样的:instance = null;请记住,我检查静态getInstance方法,我的实例不为null,否则我创建它:if (instance == null){&nbsp; &nbsp; instance = new Task();}return instance;postExecute中的方法将清空实例并重新创建它。当然这可以在课外完成。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Android