2015-10-03 3 views
0

Je viens d'écrire un code qui ajoute plusieurs vues, chacune utilisant un gestionnaire. Ceux-ci sont ajoutés en utilisant une boucle for. Ceux-ci ajoutent juste correctement. Ensuite, j'ai essayé d'ajouter un bouton après la boucle for sans utiliser de gestionnaire. Cette fois, le bouton était affiché en haut de la mise en page, c'est-à-dire AVANT les éléments ajoutés dans la boucle. Cela ne se produit pas si j'ajoute le bouton en utilisant le gestionnaire.Trouvé ce comportement étrange de Handlers dans android

Donc, si j'utilise le code suivant avec un gestionnaire après la boucle puis sur le bouton est ajouté au bas de la mise en page:

private void fillFeedWithData(final List<ParseObject> feedObjectList) { 

    LayoutInflater inflaterOfFeedItem = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

    for (int i = 0; i < feedObjectList.size(); i++) { 

     final String jokeTitle = feedObjectList.get(i).getString("content"); 

     final View cvFeedItem = inflaterOfFeedItem.inflate(R.layout.feed_item_theme_card, null); 

     final TextView tvJoke = (TextView) cvFeedItem.findViewById(R.id.tvFeedJoke); 

     Handler h2 = new Handler(); 
     Runnable update2 = new Runnable() { 
      public void run() { 
       tvJoke.setText(jokeTitle); 
       llFragmentFeedParent.addView(cvFeedItem); 
    // llFragmentFeedParent is acquired in OnCreate() method 
      } 
     }; 
     h2.post(update2); 
    } 


    final Button bNext = new Button(this); 
    bNext.setText("Next >"); 
    bNext.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); 

    Handler h3 = new Handler(); 
    Runnable update3 = new Runnable() { 
     public void run() { 
      llFragmentFeedParent.addView(bNext); 
     } 
    }; 
    h3.post(update3); 
} 

Si je le code suivant après la boucle puis sur le bouton est ajouté sur le dessus de la mise en page:

Button bNext = new Button(this); 
    bNext.setText("Next >"); 
    bNext.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); 
    llFragmentFeedParent.addView(bNext); 

Alors maintenant, mon application fonctionne comme prévu avec le gestionnaire, mais je suis préoccupé par les raisons pour lesquelles cela se passait. Je pense que les gestionnaires mélangent les horaires/séquence d'exécution? Si je continue à utiliser la logique, est-il possible que le bouton, dans un téléphone mobile lent, apparaisse au-dessus ou même entre les éléments ajoutés dans la boucle?

Répondre

2

Je ne sais pas pourquoi vous voudriez le faire de cette façon, mais pour répondre à votre question. Les gestionnaires publient les Runnables dans une file d'attente qui s'exécute dans l'ordre (en supposant que vous n'utilisiez pas postDelayed). Ils exécutent éventuellement, ce qui signifie que leur exécution dépend entièrement du nombre d'autres exécutables publiées et du temps nécessaire à l'exécution de ces exécutables. Les gestionnaires partagent en fait un thread Looper sur lequel ils sont créés (dans ce cas, le thread de l'UI Looper principal), donc peu importe le nombre de références Handler que vous créez, ils publieront dans le même thread. De même, vous pouvez passer un objet Looper d'un autre thread afin que Runnables s'exécute sur ce thread.

Dans ce cas, lorsque vous ajoutez un bouton sans le gestionnaire, vous l'ajoutez à la vue maintenant avant que votre autre gestionnaire ne s'exécute. Lorsque vous postez dans un autre gestionnaire, qui est également créé sur le thread d'interface utilisateur, il affiche le Runnable dans une file d'attente après le premier que vous avez publié. Alors, ils fonctionnent effectivement séquentiellement.

EDIT:

également dans ce cas, je serais fossé le mécanisme Handler entièrement et vient de mettre toutes les vues que vous voulez ajouter dans un List, puis les ajouter dans une collection. Vous allez publier un nouveau Runnable à chaque passage, ce qui ajoutera une nouvelle vue à la mise en page, ce qui déclenchera une passe de mise en page, qui déclenchera une passe de tirage. Il est préférable de simplement les ajouter en une seule fois.

+0

Cela signifie que le bouton s'affichera toujours dans la position désirée. En fait, chaque élément est une mise en page compliquée et je n'avais aucune idée de comment implémenter des vues personnalisées dans une liste, donc j'ai fait ma propre solution de contournement. code. Les gestionnaires aident quand il y a 100 articles, chacun avec une image. Mais vous avez raison, je devrais apprendre à utiliser des listes, ma logique sera mieux supportée par une liste. – Usman

+0

Et merci, vous avez répondu à ma question :) – Usman