web-dev-qa-db-fra.com

Ce qui déclenche l'appel d'une mesure () d'une vue

Dans mon application, j'ai une boucle infinie sur l'un des remplacements onMeasure () de View. Débogage du code source à partir d'un point d'arrêt dans mon onMeasure, je suis capable de me tracer tout le long de la trace de la pile jusqu'à la mesure () de PhoneWindow $ DecorView (la plus haute classe de ma hiérarchie de vues), qui est appelée par ViewRoot .performTraversals (). Maintenant à partir d'ici, si je continue à marcher, je reçois finalement la mesure () de PhoneWindow $ DecorView appelée à nouveau par un message dans la classe Looper.loop (). Je suppose que quelque chose a mis en file d'attente un message qu'il doit réévaluer, comme une invalidation.

Ma question est, quels déclencheurs un appel de mesure doit se produire sur une vue?

D'après ma compréhension du processus de mise en page/mesure/dessin, cela ne se produira que lorsque la méthode invalidate () est appelée sur une vue spécifique, et cela se répercutera et effectuera une passe de mise en page/mesure/dessin pour cette vue invalidée et tout ses enfants. Je suppose que ma vue la plus élevée dans ma hiérarchie de vues est invalidée.

Cependant, j'ai explicitement mis un point d'arrêt sur chaque appel invalide que j'ai, et je n'appelle pas invalider d'une manière infinie. Je ne pense donc pas que ce soit le cas. Existe-t-il un autre moyen de déclencher un passage de mesure? Quelque chose pourrait-il déclencher cela en interne? Je suis un peu à court d'idées après avoir vu que rien n'invalide l'infini.

43
C Nick

Pour déclencher une passe de mesure pour une vue personnalisée, vous devez appeler la méthode requestLayout (). Par exemple, si vous implémentez une vue personnalisée qui étend View et qu'elle se comportera comme une TextView, vous pouvez écrire une méthode setText comme ceci:

/**
 * Sets the string value of the view.
 * @param text the string to write
 */
public void setText(String text) {
    this.text = text;

            //calculates the new text width
    textWidth = mTextPaint.measureText(text);

    //force re-calculating the layout dimension and the redraw of the view
    requestLayout();
    invalidate();
}
81
moondroid

Eh bien, si vous modifiez le contenu d'une vue, elle devra éventuellement appeler invalidate (). Par exemple, vous avez un TextView avec un texte appelé "Text 1". Maintenant, vous modifiez le texte du même TextView en "Texte 2". Ici aussi, invalidate sera appelé.

Donc, fondamentalement, lorsque quelque chose change dans la vue, le plus souvent, vous vous attendez à ce que la méthode invalidate soit appelée et un appel correspondant à la mesure ().

Regardez le code source de TextView, par exemple. http://www.google.com/codesearch#uX1GffpyOZk/core/Java/Android/widget/TextView.Java&q=TextView%20package:Android&type=cs

Comptez le nombre d'appels invalides. Il y en a pas mal.

1
Kumar Bibek