web-dev-qa-db-fra.com

Comment vérifier si la tâche asynchrone est déjà en cours d'exécution

J'ai une application qui doit effectuer une opération de base de données intensive au démarrage. L'application contient une copie locale des contacts sur le téléphone et se synchronise avec la base de données de contacts Android au démarrage.

Si un utilisateur démarre l'application, une tâche asynchrone est lancée pour effectuer la synchronisation de la base de données en arrière-plan. Si l'utilisateur ferme l'application, l'opération continue de fonctionner, ce qui est correct. Cependant, si l'utilisateur ouvre à nouveau l'application, la tâche asynchrone démarre et une erreur se produit.

Est-il possible de vérifier si la tâche est déjà en cours d'exécution à partir d'une autre instance de l'application?

31
Kevin Bradshaw

Je pense que vous devriez vérifier le concept de Application dans Android. http://developer.Android.com/reference/Android/app/Application.html

En fait, il n’existe pas de

instance différente de l'application

. Le Application est toujours le même pour tous vos Activities/Services. Cela signifie que vous avez quitté le Activity et l'avez rouvert, 2 cas sont possibles:

  1. Le système a déjà tué votre application. Dans ce cas, AsyncTask est déjà mort et il est sûr d'en démarrer un nouveau
  2. Application était toujours en vie, donc AsyncTask peut-être encore en cours d'exécution.

Dans le deuxième cas, je recommanderai d'utiliser certaines variables statiques, pointant vers ce AsyncTask ou son état. Si votre application était encore en vie lors de la 2e ouverture - toutes les références statiques seront toujours valides, afin que vous puissiez fonctionner correctement.

PS: Au fait, dans l'approche actuelle, sachez que votre application peut être résiliée par le système à tout moment. Ainsi, AsyncTask peut être interrompu à tout moment. Ce n'est pas bien pour vous - veuillez vérifier IntentServices - composants, spécialement conçus pour le fonctionnement en arrière-plan. http://developer.Android.com/reference/Android/app/IntentService.html

Bonne chance!

3
AlexN

Utilisez getStatus() pour obtenir l'état de votre AsyncTask. Si le statut est AsyncTask.Status.RUNNING alors votre tâche est en cours d'exécution.

ÉDITER: vous devriez reconsidérer votre implémentation et maintenir le AsyncTask probablement dans un Service ou IntentService pour récupérer vos données sur le web.

94
Ovidiu Latcu

Oui, les gars, voici quelques exemples.

LoadMusicInBackground lmib = new LoadMusicInBackground();

if(lmib.getStatus() == AsyncTask.Status.PENDING){
    // My AsyncTask has not started yet
}

if(lmib.getStatus() == AsyncTask.Status.RUNNING){
    // My AsyncTask is currently doing work in doInBackground()
}

if(lmib.getStatus() == AsyncTask.Status.FINISHED){
    // My AsyncTask is done and onPostExecute was called
}
33
Ahmad Arslan

J'ai réussi à gérer ce problème avec une sorte de motif Singleton. J'espère que cela aide.

// fill the places database from a JSON object
public class myAsyncTask extends AsyncTask<Void,Integer,Integer> {

    Activity mContext = null;
    static AsyncTask<Void,Integer,Integer> myAsyncTaskInstance = null; 

    // Private Constructor: can't be called from outside this class
    private myAsyncTask(Activity iContext) {
        mContext = iContext; 
    }

    public static AsyncTask<Void, Integer, Integer> getInstance(Activity iContext) {
        // if the current async task is already running, return null: no new async task 
        // shall be created if an instance is already running
        if (myAsyncTaskInstance != null && myAsyncTaskInstance.getStatus() == Status.RUNNING) {
            // it can be running but cancelled, in that case, return a new instance
            if (myAsyncTaskInstance.isCancelled()) {
                myAsyncTaskInstance = new myAsyncTask(iContext);
            } else {
                // display a toast to say "try later"
                Toast.makeText(iContext, "A task is already running, try later", Toast.LENGTH_SHORT).show();    

                return null;
            }
        }

        //if the current async task is pending, it can be executed return this instance
        if (myAsyncTaskInstance != null && myAsyncTaskInstance.getStatus() == Status.PENDING) {
            return myAsyncTaskInstance;
        }

        //if the current async task is finished, it can't be executed another time, so return a new instance
        if (myAsyncTaskInstance != null && myAsyncTaskInstance.getStatus() == Status.FINISHED) {
            myAsyncTaskInstance = new myAsyncTask(iContext);
        }


        // if the current async task is null, create a new instance
        if (myAsyncTaskInstance == null) {
            myAsyncTaskInstance = new myAsyncTask(iContext);
        }
        // return the current instance
        return myAsyncTaskInstance;
    }

    @Override
    protected Integer doInBackground(Void... iUnUsed) {
        // ...
    }
}
6
Jeremy Heitz