IT

AsyncTask를 여러 번 실행

lottoking 2020. 7. 5. 07:44
반응형

AsyncTask를 여러 번 실행


내 활동에서는 AsyncTask에서 확장되는 클래스와 해당 AsyncTask의 인스턴스 인 매개 변수를 사용합니다. 내가 전화하면 mInstanceOfAT.execute("")모든 것이 괜찮습니다. 그러나 AsyncTask를 다시 호출하는 업데이트 버튼을 누르면 앱이 중단됩니다 (네트워크 작업이 작동하지 않은 경우). 그런 다음 원인은 예외를 나타냅니다

작업을 실행할 수 없음 : 작업이 이미 실행되었습니다 (작업은 한 번만 실행할 수 있음)

Asyctask 인스턴스에 대해 cancel (true)을 호출하려고 시도했지만 작동하지 않습니다. 지금까지 유일한 솔루션은 Asyntask의 새 인스턴스를 작성하는 것입니다. 이것이 올바른 방법입니까?

감사.


AsyncTask 인스턴스는 한 번만 사용할 수 있습니다.

대신, 다음과 같이 작업을 호출하십시오. new MyAsyncTask().execute("");

AsyncTask API 문서에서 :

스레딩 규칙

이 클래스가 제대로 작동하려면 몇 가지 스레딩 규칙을 따라야합니다.

  • 작업 인스턴스는 UI 스레드에서 작성해야합니다.
  • UI 스레드에서 execute (Params ...)를 호출해야합니다.
  • onPreExecute (), onPostExecute (Result), doInBackground (Params ...), onProgressUpdate (Progress ...)를 수동으로 호출하지 마십시오.
  • 작업은 한 번만 실행할 수 있습니다 (두 번째 실행을 시도하면 예외가 발생 함).

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();
    }
}

Of course, this is slightly more complicated than the traditional usage of ASyncTask, and you give up the use of publishProgress() for actual progress reporting. But if memory is your concern, then this approach will ensure only one ASyncTask remains in the heap at runtime.


I had the same issue. In my case i have a task i want to do in onCreate() and in onResume(). So i made my Asynctask static, and get the instance from it. Now we still have the same problem.

So what i did in the onPostExecute() is this:

instance = null;

Keeping in mind that i check in the static getInstance method that my instance isn't null, else i create it:

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

The method in postExecute will empty the instance and recreate it. Of course this can be done outside the class.


I have made my rotation tasks static, which then helped me attach, detach, and reattach them to UI threads on rotation changes. But to go back to your question, what I do is create a flag to see if the thread is running. When you want to restart the thread I check if the rotation task is running if it is I toast a warning. If it is not, I make it null and then create a new one, which will work around the error you are seeing. Furthermore, upon successful completion I null out the completed rotation aware task so that it is ready to go again.


Yes it is true, the doc says that only can be executed one Asyntask.

Every time that you need to use it you have to instance:

// 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> {
}

참고URL : https://stackoverflow.com/questions/6373826/execute-asynctask-several-times

반응형