2017-08-11 3 views
0

pour la première fois à écrire un AsyncTask et je semble avoir un défaut de conception subtile qui empêche à la fois ProgressDialog, ProgressBar, et même Log.d() de fonctionner correctement. Je soupçonne que je ne suis pas en train de créer un nouveau thread/tâche.Android: comportement AsyncTask contraire à la documentation de

court: les symptômes

  • Un ProgressDialog est créé dans le constructeur, et les commandes du code Android pour les afficher en onPreExecute(), mais la boîte de dialogue montre jamais.

  • onProgressUpdate() est supposé exécuter chaque fois que j'appelle publishProgress() de doInBackground(), correct? Eh bien, ce n'est pas le cas. Au lieu de cela, il s'exécute lorsque doInBackground() se termine.

longues: enquêtes

choses que j'ai vérifié par l'émulateur et, lorsque cela est possible, sur un téléphone:

  • onPreExecute() est certainement appelé

    • les progrès la barre n'est pas remise à doInBackground() complète

    • update_dialog.show() est définitivement exécuté, mais la boîte de dialogue n'apparaît que si je supprime le .dismiss() dans onPostExecute(); J'imagine dialogue est, comme la barre de progression, non montré qu'après doInBackground() terminée, mais est naturellement rejeté immédiatement

    • le code montrera heureusement les boîtes de dialogue lorsqu'aucun calcul est impliqué

  • doInBackground() invoque certainement publishProgress()

    • ne s'exécute pas immédiatement! c'est-à-dire, j'ai un point d'arrêt dans la fonction, et le débogueur ne s'arrête pas là jusqu'à ce que après doInBackground() se termine! (Peut-être cela est un phénomène du débogueur, plutôt que doInBackground(), mais j'observe les mêmes symptômes sur un appareil mobile)

    • la barre de progression est mise à jour ... seulement après doInBackground() tout termine

    • De même, les données Log.d() apparaît dans Android Moniteur seulement après doInBackground() tout termine

  • et bien sûr la boîte de dialogue ne se présente pas non plus dans l'émulateur ou sur un périphérique (à moins que je supprimer .dismiss() de onPostExecute())

Quelqu'un peut-il aider à trouver le problème?Idéalement, je voudrais un dialogue de travail, mais comme Android a déconseillé de toute façon que je serais bien avec une barre de progression de travail.

code

Voici l'essentiel, moins les détails de calcul & c .:

Où j'appelle le AsyncTask du fil conducteur:

if (searching) { // this block does get executed! 
    Compute_Task my_task = new Compute_Task(overall_context, count); 
    my_task.execute(field, count, max_x, max_y); 
    try { result = my_task.get(); } catch (Exception e) { } 
} 

lui-même AsyncTask:

private class Compute_Task extends AsyncTask<Object, Integer, Integer> { 

    public Compute_Task(Context context, int count) { 
     super(); 
     current_positions = 0; 
     update_dialog = new ProgressDialog(context); 
     update_dialog.setIndeterminate(true); 
     update_dialog.setCancelable(false); 
     update_dialog.setTitle("Thinking"); 
     update_dialog.setMessage("Please wait"); 
    } 

    protected void onPreExecute() { 
     super.onPreExecute(); 
     update_dialog.show(); 
     ProgressBar pb = ((ProgressBar) ((Activity) overall_context).findViewById(R.id.progress_bar)); 
     pb.setMax(base_count); 
     pb.setProgress(0); 
    } 

    protected void onPostExecute() { 
     super.onPostExecute(); 
     update_dialog.dismiss(); 
    } 

    protected void onProgressUpdate(Integer... values) { 
     super.onProgressUpdate(values); 
     ProgressBar pb = ((ProgressBar) ((Activity) overall_context).findViewById(R.id.progress_bar)); 
     pb.setMax(base_count); 
     pb.incrementProgressBy(1); 
     Log.d(tag, values[0].toString()); 
    } 

    protected Integer doInBackground(Object... params) { 
     Integer result = compute_scores(
     (boolean[][]) params[0], (Integer) params[1], (Integer) params[2], (Integer) params[3], 0) 
    ); 
     return result; 
    } 

    public int compute_scores(boolean[][] field, int count, int max_x, int max_y, int level) { 
     int result, completed = 0; 
     switch(count) { 
     // LOTS of computation goes on here, 
     // including a recursive call where all params are modified 
     if (level == 0) 
      publishProgress(++completed); 
     } 
    } 

    ProgressDialog update_dialog; 

} 

Répondre

0

Il s'avère que c'est fondamentalement le même problème que celui donné here. La ligne "fatale" est celle-ci:

try { result = my_task.get(); } catch (Exception e) { } 

Apparemment cela met le thread de l'interface utilisateur dans un profond sommeil. On ne devrait pas utiliser get() avec un AsyncTask sauf si l'on est prêt à suspendre le thread UI. Nous devons effectuer un peu de magie dans onPostExecute() à la place.

Bien qu'il se soit avéré qu'il s'agissait d'un doublon, je ne l'ai trouvé qu'après l'avoir écrit, car je ne m'étais pas rendu compte que le fil bloquait.