Loupe

Android : gagnez en performances en ne chargeant votre interface que si elle est vraiment nécessaire avec les ViewStub

Les vues Android sont définies en XML et cela implique que pour chaque affichage, une lecture et interprétation de cet XML est nécessaire par le moteur de rendu Android. Cela a un impact sur les performances qui n'est pas forcément négligeable. Dans cet article nous verrons comment optimiser cette partie en utilisant les ViewStub Android.

Qu'est ce que c'est qu'un ViewStub ?

C'est tout simplement un composant qui sert de repère dans votre XML. Il ne sera pas chargé et ne prendra pas d'espace en mémoire tant que vous n'en avez pas réellement besoin. 

Il sera bien présent dans votre hiérarchie XML, vous pouvez le trouver avec FindViewById mais il ne fera rien en tant que tel. C'est donc parfait pour mettre dans votre hiérarchie une vue qui ne serait pas toujours nécessaire : vous ne la chargerez qu'au besoin. L'affichage initial de votre vue en sera ainsi plus performant car allégé de cette partie. Il va sans dire que cela n'est à faire que sur des morceaux conséquents d'XML.

 

Utilisation d'un ViewStub

La première étape est bien sûr de la déclarer dans l'XML de votre vue. On prendra soin de renseigner l'attribut "android:layout" en spécifiant un fichier de layout à utiliser lorsque l'on chargera le ViewStub. Pensez à bien respecter une case en minuscule ici.

<ViewStub android:id="@+id/Home_SearchViewStub"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout="@layout/Home_SearchViewStub"/>

 

Pour charger la ViewStub on va simplement utiliser sa méthode Inflate. Pour plus de facilité d'utilisation, j'aime créer une instance de Lazy<MaVueChargée> dans la méthode OnCreate de mon activité.

_maView = new Lazy<MaVueChargée>(
		() => (MaVueChargée)FindViewById<ViewStub>(Resource.Id.Home_SearchViewStub)
		.Inflate());

 

Pour accéder à votre vue, il suffira d'utiliser la propriété "Value" de votre Lazy. On peut alors rechercher des sous-vues avec FindViewById de manière classique. Dans mon cas, je charge une vue personnalisée contenant une méthode Show que je peux appeler directement : 

_maView.Value.Show();
_maView.Value.FindViewById<View>(Resource.Id.Home_UneSousVue)

 

Dans certain cas, comme la gestion du bouton back, j'ai besoin de vérifier si ma vue est ouverte. Pour cela il faut prendre soin de vérifier en premier si elle a déjà été créée sous peine de déclencher son chargement:

if (_maView.IsValueCreated && _maView.Value.IsOpen)
 {
     _maView.Value.Close();
     return;
 }

 

Aussi, si par la suite vous avez besoin d'accéder à nouveau à la vue via FindViewById, il est possible d'ajouter un attribut "android:InflatedId" sur le ViewStub. Dans notre cas, cela a peu de sens car on stocke sa référence.

<ViewStub android:id="@+id/Home_SearchViewStub"
            android:id="@+id/Home_SearchViewInflated"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout="@layout/Home_SearchViewStub"/>

 

Comme je n'oublie pas mes anciens amours, sur Windows et la plateforme UWP on aurait utilisé l'attribut x:DeferLoadStrategy pour obtenir un comportement similaire ! 

 

Happy coding :)

Photo de profil

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus