首页 文章

多次执行AsyncTask

提问于
浏览
125

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

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

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

谢谢 .

5 回答

  • 1

    AsyncTask 实例只能使用一次 .

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

    来自AsyncTask API文档:

    线程规则

    此类必须遵循一些线程规则才能正常工作:

    • 必须在UI线程上创建任务实例 .
      必须在UI线程上调用

    • execute(Params ...) .

    • 不要手动调用onPreExecute(),onPostExecute(Result),doInBackground(Params ...),onProgressUpdate(Progress ...) .

    • The task can be executed only once (an exception will be thrown if a second execution is attempted.)

  • 213

    在Steve Prentice的回答中详细说明了ASyncTask发生故障的实例 - 但是,当您执行ASyncTask的次数受到限制时,您可以在线程运行时自由地执行您喜欢的操作 . .

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

    Example:

    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保留在堆中 .

  • 0

    我遇到过同样的问题 . 在我的情况下,我有一个任务,我想在 onCreate()onResume( ) . 所以我使我的Asynctask静态,并从中获取实例 . 现在我们仍然有同样的问题 .

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

    instance = null;
    

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

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

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

  • 28

    我已将旋转任务设置为静态,然后帮助我在旋转更改时附加,分离并重新连接到UI线程 . 但是回到你的问题,我所做的是创建一个标志来查看线程是否正在运行 . 如果要重新启动线程,我会检查旋转任务是否正在运行,如果它是我举报警告 . 如果不是,我将其设为null然后创建一个新的,它将解决您看到的错误 . 此外,在成功完成后,我将完成的旋转感知任务归零,以便它可以再次运行 .

  • 2

    是的,这是真的,医生说只能执行一个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> {
    }
    

相关问题