Comprendre RecyclerView setHasFixedSize

J’ai du mal à comprendre setHasFixedSize() . Je sais qu’il est utilisé pour l’optimisation lorsque la taille de RecyclerView ne change pas, à partir des documents.

Qu’est-ce que ça veut dire cependant? Dans la plupart des cas, un ListView presque toujours une taille fixe. Dans quels cas ne serait-ce pas une taille fixe? Est-ce que cela signifie que l’immobilier réel qu’il occupe à l’écran augmente avec le contenu?

Une version très simplifiée de RecyclerView a:

 void onItemsInsertedOrRemoved() { if (hasFixedSize) layoutChildren(); else requestLayout(); } 

Ce lien explique pourquoi l’appel de requestLayout peut être coûteux. Fondamentalement, chaque fois que des éléments sont insérés, déplacés ou supprimés, la taille (largeur et hauteur) de RecyclerView peut changer et, à son tour, la taille de toute autre vue dans la hiérarchie de la vue peut changer. Cela est particulièrement gênant si des éléments sont ajoutés ou supprimés fréquemment.

Évitez les passes de mise en page inutiles en définissant setHasFixedSize sur true lorsque la modification du contenu de l’adaptateur ne modifie pas sa hauteur ou sa largeur.


Mise à jour: JavaDoc a été mis à jour pour mieux décrire ce que la méthode fait réellement.

RecyclerView peut effectuer plusieurs optimisations s’il peut savoir à l’avance que la taille de RecyclerView n’est pas affectée par le contenu de l’adaptateur. RecyclerView peut toujours modifier sa taille en fonction d’autres facteurs (par exemple, la taille de son parent), mais ce calcul de taille ne peut pas dépendre de la taille de ses enfants ou du contenu de son adaptateur (sauf le nombre d’éléments de l’adaptateur).

Si votre utilisation de RecyclerView appartient à cette catégorie, définissez-la sur {@code true}. Cela permettra à RecyclerView d’éviter d’invalider la mise en page entière lorsque le contenu de son adaptateur change.

@param hasFixedSize true si les modifications de l’adaptateur ne peuvent pas affecter la taille de RecyclerView.

Peut confirmer que setHasFixedSize concerne le RecyclerView lui-même, et non la taille de chaque élément adapté.

Vous pouvez maintenant utiliser android:layout_height="wrap_content" sur un RecyclerView, qui permet, entre autres choses, à CollapsingToolbarLayout de savoir qu’il ne doit pas être réduit lorsque RecyclerView est vide. Cela ne fonctionne que lorsque vous utilisez setHasFixedSize(false) sur RecylcerView.

Si vous utilisez setHasFixedSize(true) sur RecyclerView, ce comportement pour empêcher le CollapsingToolbarLayout de se réduire ne fonctionne pas, même si RecyclerView est effectivement vide.

Si setHasFixedSize était liée à la taille des éléments, cela ne devrait pas avoir d’effet lorsque le programme RecyclerView ne contient aucun élément.

Le ListView avait une fonction nommée similaire qui, je pense, reflétait des informations sur la taille de la taille individuelle des éléments de la liste. La documentation de RecyclerView indique clairement qu’il fait référence à la taille du RecyclerView lui-même, et non à la taille de ses éléments.

A partir du commentaire source RecyclerView au-dessus de la méthode setHasFixedSize ():

  * RecyclerView can perform several optimizations if it can know in advance that changes in * adapter content cannot change the size of the RecyclerView itself. * If your use of RecyclerView falls into this category, set this to true. 

setHasFixedSize (true) signifie que RecyclerView a des enfants (éléments) ayant une largeur et une hauteur fixes. Cela permet au RecyclerView de mieux optimiser en définissant la hauteur et la largeur exactes de la liste complète en fonction de votre adaptateur.

Cela affecte les animations de la recyclerview, si c’est false . Les animations d’insertion et de suppression ne seront pas affichées. alors assurez-vous que c’est true au cas où vous appendiez une animation pour la recyclerview.

Si la taille du RecyclerView (le RecyclerView lui-même)

… ne dépend pas du contenu de l’adaptateur:

 mRecyclerView.setHasFixedSize(true); 

… dépend du contenu de l’adaptateur:

 mRecyclerView.setHasFixedSize(false);