128 votes

Que fait exactement la méthode post ?

J'ai rencontré une fonctionnalité très bizarre.

Lorsque j'essaie d'exécuter une animation sur le fil principal, elle ne démarre pas. Lorsque je lance cette animation en utilisant

getView().post(new Runnable() {
            @Override
            public void run() {
                getView().startAnimation(a);
            }
        });

Ça commence.

J'ai imprimé le CurrentThread avant de démarrer l'animation et les deux impressions main .

Manifestement, j'ai raté quelque chose ici, car les deux devraient démarrer l'animation sur le fil principal... Je pense que lorsque post ajoute la tâche à la file d'attente, elle démarre à un moment plus "correct", mais j'aimerais savoir ce qui se passe ici de manière plus approfondie.

EDIT : Permettez-moi de clarifier les choses - ma question est de savoir pourquoi le démarrage de l'animation sur le poste provoque son démarrage, alors que le démarrage de l'animation sur le fil principal ne le fait pas.

170voto

Talha Points 6003

poste :post provoque l'ajout du Runnable à la file d'attente des messages,

Runnable : Représente une commande qui peut être exécutée. Souvent utilisée pour exécuter du code dans un Thread différent.

exécuter () : Commence à exécuter la partie active du code de la classe. Cette méthode est appelée lors du démarrage d'un thread qui a été créé avec une classe qui implémente Runnable.

getView().post(new Runnable() {

         @Override
         public void run() {
             getView().startAnimation(a);
         }
     });

code : getView().startAnimation(a);

dans votre code,

fait en sorte que le Runnable (le code sera exécuté dans un thread différent) pour ajouter la file d'attente des messages.

Ainsi, startAnimation sera déclenchée dans un nouveau fil d'exécution lorsqu'elle sera récupérée dans la base de données de l'UE. messageQueueue

[EDIT 1]

Pourquoi utiliser un nouveau thread au lieu du thread UI (main thread) ?

UI Thread :

  • Lorsque l'application est lancée, l'Ui Thread est créé automatiquement.

  • il est chargé de distribuer les événements aux widgets appropriés. et cela inclut les événements de dessin.

  • C'est aussi le fil conducteur qui vous permet d'interagir avec les widgets Android avec

Par exemple, si vous touchez un bouton à l'écran, le thread de l'interface utilisateur transmet l'événement de contact au widget qui, à son tour, définit ses paramètres. envoie l'événement tactile au widget qui, à son tour, définit son état état enfoncé et envoie une demande d'invalidation à la file d'attente des événements. Le thread d'interface utilisateur thread de l'interface utilisateur met la demande en file d'attente et notifie au widget de redessiner lui-même.

Que se passe-t-il si un utilisateur appuie sur un bouton qui déclenche une opération longue ?

((Button)findViewById(R.id.Button1)).setOnClickListener(           
             new OnClickListener() {        
        @Override
    public void onClick(View v) {
            final Bitmap b = loadImageFromNetwork();
            mImageView.setImageBitmap(b);
}
});

L'interface utilisateur se fige. Le programme peut même se bloquer.

public void onClick(View v) {
  new Thread(new Runnable() {
    public void run() {
        final Bitmap b = loadImageFromNetwork();
        mImageView.setImageBitmap(b);
    }
  }).start();
}

Il enfreint la règle d'Android selon laquelle ne jamais mettre à jour l'interface utilisateur directement à partir du fil de travail

Android offre plusieurs façons d'accéder au thread de l'interface utilisateur à partir d'autres threads.

  • Activité.runOnUiThread(Runnable)
  • View.post(Runnable)
  • View.postDelayed(Runnable, long)
  • Manipulateur

Comme ci-dessous,

View.post(Runnable)

public void onClick(View v) {
  new Thread(new Runnable() {
    public void run() {
      final Bitmap b = loadImageFromNetwork();
      mImageView.post(new Runnable() {
        public void run() {
          mImageView.setImageBitmap(b);
        }
      });
    }
  }).start();
}

Manipulateur

final Handler myHandler = new Handler(Looper.getMainLooper());

(new Thread(new Runnable() {

    @Override
    public void run() {
       final Bitmap b = loadImageFromNetwork();
      myHandler.post(new Runnable() {                           

        @Override
        public void run() {
           mImageView.setImageBitmap(b);
          }
        });
      }
    })).start();                
}

enter image description here

Pour plus d'informations

http://Android-developers.blogspot.com/2009/05/painless-threading.html

http://www.aviyehuda.com/blog/2010/12/20/Android-multithreading-in-a-ui-environment/

45voto

Joe Plante Points 2733

Est-ce que cela se fait sur onCreate ou onCreateView ? Si c'est le cas, l'application n'est peut-être pas dans un état où la vue est attachée à la fenêtre. De nombreux algorithmes basés sur les métriques de la vue peuvent ne pas fonctionner, car des éléments comme les mesures et la position de la vue peuvent ne pas avoir été calculés. Les animations Android nécessitent généralement de passer par les mathématiques de l'interface utilisateur.

View.post met en fait l'animation en file d'attente dans la boucle de messages de la vue, de sorte qu'une fois la vue attachée à la fenêtre, elle exécute l'animation au lieu de la faire exécuter manuellement.

Vous exécutez en fait des choses sur le thread de l'interface utilisateur, mais à un moment différent.

20voto

Tas Morf Points 984

Jetez un coup d'œil ici pour une bonne réponse. view.post() est identique à handler.post() à peu près. Elle est placée dans la file d'attente du thread principal et est exécutée une fois que les autres tâches en attente sont terminées. Si vous appelez activity.runOnUiThread(), il sera appelé immédiatement sur le thread de l'interface utilisateur.

6voto

carrizo Points 438

Je pense que le problème pourrait venir de la méthode du cycle de vie où vous appelez la méthode post(). Le faites-vous dans onCreate() ? Si oui, regardez ce que j'ai trouvé dans la documentation onResume() de l'activité :

onResume()

Ajouté dans l'API niveau 1 void onResume () Appelé après onRestoreInstanceState(Bundle), onRestart() ou onPause(), pour que votre activité commence à interagir avec l'utilisateur. activité commence à interagir avec l'utilisateur. C'est un bon endroit pour commencer les animations les dispositifs ouverts à accès exclusif (tels que le système d'alerte précoce). caméra), etc.

[https://developer.Android.com/reference/Android/app/Activity.html#onResume()](https://developer.android.com/reference/android/app/Activity.html#onResume())

Donc, comme l'a dit Joe Plante, peut-être que la vue n'est pas prête à démarrer les animations au moment où vous appelez post(), alors essayez de le déplacer vers onResume().

PD : En fait, si vous déplacez le code vers onResume(), je pense que vous pouvez supprimer l'appel post() puisque vous êtes déjà dans le ui-thread et que la vue devrait être prête à démarrer les animations.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X