多次执行AsyncTask

Day*_*man 127 android android-asynctask

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

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

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

谢谢.

Ste*_*ice 217

AsyncTask 实例只能使用一次.

相反,只需将您的任务称为 new MyAsyncTask().execute("");

来自AsyncTask API文档:

线程规则

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

  • 必须在UI线程上创建任务实例.
  • 必须在UI线程上调用execute(Params ...).
  • 不要手动调用onPreExecute(),onPostExecute(Result),doInBackground(Params ...),onProgressUpdate(Progress ...).
  • 该任务只能执行一次(如果尝试第二次执行,则会抛出异常.)

  • @ Ant4res,只要您没有引用异步任务实例,GC就会释放内存.但是,如果您正在进行后台任务,则可以考虑在doInBackground内部循环中执行此操作,并调用publishProgress来更新进度.或者,另一种方法是将您的任务放入后台线程.这里有很多不同的方法,但不能在没有细节的情况下推荐一个. (3认同)
  • 我说我做过的,是唯一的可能性吗?因为我想保存memmory,而不是创建一个新对象. (2认同)

sea*_*ges 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,这比传统的ASyncTask使用稍微复杂一点,并且您放弃使用publishProgress()进行实际的进度报告.但是如果你担心内存,那么这种方法将确保在运行时只有一个ASyncTask保留在堆中.