web-dev-qa-db-fra.com

Android attendez AsyncTask pour terminer

J'ai une fonction, AppHelper.isOnline(Context context), j'appelle dans différentes parties de mon application pour vérifier qu'une session n'a pas expiré avant de faire une requête HTTP.

public void onClick(View v) {
        Intent intent = null;
        switch (v.getId()) {

        case R.id.buttonPagamenti:
            if (AppHelper.isOnline(this))
            {
                //here AppHelper.isOnline should have finished it's async task
                intent = new Intent(this, OrdineCreaActivity.class);
                this.startActivityForResult(intent, R.id.buttonPagamenti);
            }
            break;
...

Dans AppHelper.isOnline(), j'exécute un AsyncTask qui se connecte, faisant ainsi une requête réseau, qui ne peut pas être exécutée sur l'interface utilisateur car sinon j'obtiens une exception. Je dois attendre qu'il se termine AVANT de reprendre avec le code à l'intérieur de l'if. Comment puis-je faire ceci ?

Le problème est que l'activité commence d'abord, puis le AsyncTask s'exécute, donc lorsque l'activité attend une session connectée valide, elle se casse.

37
max4ever

Vous avez deux options:

Soit utilisez la méthode AsyncTaskget(long timeout, TimeUnit unit) comme ça:

task.get(1000, TimeUnit.MILLISECONDS);

Cela fera attendre votre thread principal le résultat de AsyncTask au maximum 1000 millisecondes (selon le commentaire @ user1028741: en fait, il existe également une méthode d'attente infinie - AsyncTask#get() = qui pourrait également faire le travail pour vous dans certains cas).

Vous pouvez également afficher une boîte de dialogue de progression dans la tâche asynchrone jusqu'à la fin. Voir ceci thread (Pas besoin de copier après le code). Fondamentalement, une boîte de dialogue de progression s'affiche pendant l'exécution de la tâche asynchrone et est masquée à la fin.

Vous avez même une troisième option: "si Thread est suffisant pour vos besoins, vous pouvez simplement utiliser sa méthode join. Cependant, si la tâche prend du temps, vous devrez toujours afficher une progression , sinon vous obtiendrez une exception car le thread principal est inactif trop longtemps.

81
Boris Strandjev

essayez d'utiliser

if (AppHelper.isOnline(this))
        {
            while(!task.isCancelled()){
               // waiting until finished protected String[] doInBackground(Void... params)          
              } 
            intent = new Intent(this, OrdineCreaActivity.class);
            this.startActivityForResult(intent, R.id.buttonPagamenti);
        }    

Pour plus d'informations, consultez http://developer.Android.com/reference/Android/os/AsyncTask.html

3
Rafiq

La réponse de Rafiq n'a pas fonctionné pour moi - l'application s'est bloquée. Je pense que la raison a à voir avec la nature de isCancelled (): "Retourne vrai si cette tâche a été annulée avant qu'elle ne se termine normalement." Si la tâche se termine normalement (c'est-à-dire qu'elle n'est pas annulée), while(!task.isCancelled()) { } sera bouclé pour toujours.

Pour résoudre ce problème, créez un indicateur booléen que vous installez dans false, puis basculez vers true dans task.onPostExecute(). Ensuite, faites while(!flag) { } avant de changer d'activités. De plus, si vous souhaitez donner une pause au thread principal pour laisser le processus AsyncTask un peu plus rapide, vous pouvez essayer ceci:

while (!flag) {
    try { Thread.sleep(100); }
    catch (InterruptedException e) { e.printStackTrace(); }
}

Cela semble bien fonctionner pour moi.

1
Mark Cramer
intent = new Intent(this, OrdineCreaActivity.class);
context.startActivityForResult(intent, R.id.buttonPagamenti);

Écrivez les lignes ci-dessus dans onPostExecute () de votre AysncTask. Parce que si nous utilisons AsyncTask, il n'attendra pas là jusqu'à ce que la tâche soit terminée.

1
Shankar Agarwal