首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >多次执行AsyncTask

多次执行AsyncTask
EN

Stack Overflow用户
提问于 2011-06-16 22:47:09
回答 5查看 96.2K关注 0票数 129

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

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

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

谢谢。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-06-16 22:49:03

AsyncTask实例只能使用一次。

取而代之的是,将你的任务命名为new MyAsyncTask().execute("");

在AsyncTask应用编程接口文档中:

线程化规则

要让这个类正常工作,必须遵循一些线程规则:

必须在UI thread.

  • execute(Params...)上创建
  • 任务实例必须在UI线程上调用。
  • 不调用onPreExecute()、onPostExecute(结果)、doInBackground(参数...)、onProgressUpdate(进度...)manually.
  • The任务只能执行一次(如果第二次执行为attempted.)

,则会引发异常

票数 218
EN

Stack Overflow用户

发布于 2011-06-16 23:09:57

Steve Prentice的回答很好地解释了ASyncTask“即发即忘”实例的原因--然而,当你执行一个ASyncTask的次数受到限制时,你可以在线程运行时自由地做你喜欢的事情……

将可执行代码放在doInBackground()内的循环中,并使用并发锁来触发每次执行。您可以使用publishProgress()/onProgressUpdate()检索结果。

示例:

代码语言:javascript
复制
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。

票数 28
EN

Stack Overflow用户

发布于 2016-03-04 19:51:03

我也有同样的问题。在我的例子中,我有一个任务,我想用onCreate()onResume(来完成)。所以我把我的Asynctask设为静态的,并从中获取实例。现在我们仍然有同样的问题。

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

代码语言:javascript
复制
instance = null;

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

代码语言:javascript
复制
if (instance == null){
    instance = new Task();
}
return instance;

postExecute中的方法将清空实例并重新创建它。当然,这可以在课外完成。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6373826

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档