Android_ListView_Introduction 1 Android ListView, ListActivity une introduction Notes de cours jean-michel Douin, douin au cnam point fr version : 28 Mars 2013
Android_ListView_Introduction1
Android ListView, ListActivity une introduction
Notes de cours
jean-michel Douin, douin au cnam point frversion : 28 Mars 2013
Android_ListView_Introduction2
Sommaire
• Vue– ListView
• Présentation
– Adapter la Vue d’une liste d’items aux souhaits du programmeur• Le patron Stratégie
– Utiliser des stratégies d’affichage standard– Installer sa propre stratégie
• Accès aux ressources décrites en XML– Optimiser ces accès (cache), recyclage
– Filtrage, tri
• Contrôleur– View / Activity
• OnItemClickListener, onItemClick
– ListView / ListActivity• onListItemClick• onItemLongClick
Technique …– Chargement d’une liste et AsyncTask
Android_ListView_Introduction3
Bibliographie utilisée
http://developer.android.com/resources/index.html
Le cours de Victor Matos
http://grail.cba.csuohio.edu/~matos/notes/cis-493/Android-Syllabus.pdf
http://www.vogella.com/android.html
Plusieurs livres
Android A Programmers Guide - McGraw Hill
Professional Android Application Development – Wrox
Le livre de Mark Murphy - Pearson
Une vidéo youtube Google IO the world of ListView par Romain Guy
http://www.youtube.com/watch?v=wDBM6wVEO70
Android_ListView_Introduction4
Présentation d’une liste d’items
• Un composant graphique commun– À un grand nombre d’applications
Android_ListView_Introduction5
Item de la liste
• Un texte par Item soitLinearLayout +TextView(standard, prédéfini)
• Chaque item de la liste est une View
• Une Image, Un titre, un nombre
LinearLayout + TableRow + ImageView + TextViewDéfini par l’application
Android_ListView_Introduction6
ListView Vue
• Une liste de vues présentant des items
• Chaque item s’affiche selon un format, – Format défini en XML,– Un adaptateur se charge de l’affichage,
• Un style de présentation, une stratégie d’affichage, est choisie
• Il existe des stratégies standard– Une liste d’items constituée de noms séparés d’un trait,
• ArrayAdapter– Une liste d’items constituée d’une grille,
• SimpleAdapter,– Une liste d’items, reflet d’une interrogation dans une base de données
• CursorAdapter– Des adaptateurs créés par le programmeur
• BaseAdapter est la classe toute prête qu’ il suffira de dériver
Android_ListView_Introduction7
Vue, Contrôleur et Modèle
• Vue La vue de la liste et sa stratégie d’affichage– Les items s’affichent selon une stratégie
• Standard, prédéfinie• Style de présentation, stratégie d’affichage définie par l’utilisateur
– setAdapter
• Contrôleur Les interactions avec l’utilisateur– A chaque clic sur l’un des items une action est déclenchée
• Une action est déclenchée, un menu apparaît…– onItemClickListener et ListView, Activity– onListItemClick au sein d’une ListActivity
• Modèle La liste des objets Java représente le modèle– List<Item>, Item[], toute collection (une classe Java,…)– Tout changement d’état du modèle sera notifié à la vue
• Adéquation Vue/Modèle prise en charge par Android– getAdapter().notifyDataSetChanged();
Android_ListView_Introduction8
Vue, style d’affichage
• Vue La vue de la liste et sa stratégie d’affichage
– Les items s’affichent selon une stratégie– setAdapter
• Standard, prédéfinie
• Style de présentation, stratégie d’affichage définie par l’utilisateur
• Patron Strategy– Usage classique : Layout en Swing– http://best-practice-software-engineering.ifs.tuwien.ac.at/patterns/strategy.html
– Un rappel en quatre diapositives
Android_ListView_Introduction9
Le patron stratégie, l’original
• Strategy– Une interface commune
• ConcreteStrategy– Quelle stratégie effective ?
• Context– Utilisation d’une stratégie choisie par le client, à la configuration
• http://www.dofactory.com/Patterns/PatternStrategy.aspx
Android_ListView_Introduction10
Le patron stratégie, l’original
• Strategy– Une interface commune pour tous les affichages
• Android : ListAdapter• ConcreteStrategy
– Quelle stratégie pour quel rendu ?
• Android : ArrayAdapter, SimpleAdapter, CursorAdapter, BaseAdapter, MonAdaptateur, MaStratégieDAffichage …
• Context– Utilisation d’une stratégie choisie par le client
• Android : ListView
Android_ListView_Introduction11
Un exemple : Usage du patron Strategy
Le patron Strategy / API Android
Classe Strategy / android.widget.Adapter
Classe ConcreteStrategy / android.widget.ArrayAdapter– Son usage (ici simplifié) avec le nom des classes des API Android
Android_ListView_Introduction12
Adapter, ListAdapter
android.widget.ArrayAdapter est une stratégie concrète toute prête
Dans laquelle ces 3 méthodes sont implémentées, pour chaque item
getCount, le nombre d’items
getItem, l’item à cette position
getView, la vue de cet item
Android_ListView_Introduction13
Adapter, ListAdapter + ListView
ListView liste = (ListView)findViewById(R.id.liste);
liste.setAdapter(new ArrayAdapter ( ….
Android_ListView_Introduction14
Un premier exemple et son affichage
• La ListView est décrite en XML– Le fichier res/layout/liste.xml– Avec une stratégie prédéfinie
• setAdapter( new ArrayAdapter<String>(contexte,
Ressource_XML_Prédéfinie, String[] modèle
• Une Activity– Un affichage
• setContentView
• Un modèle– Un diplôme Cnam constitué de plusieurs unités d’enseignement
• NFP121, NSY102, RSX116, SMB116, SMB117, UARS01– String[] ou List<String>
Android_ListView_Introduction15
Le fichier res/layout/liste.xml
– La liste est un composant graphique, son identifiant R.id.listeId
La ListView est décrite en XML
Android_ListView_Introduction16
Une activity, onCreate, affectation de la Vue
• Redéfinition de la méthode onCreate– Cumul du comportement– Affectation de la Vue (res/layout/liste.xml)
• setContentView– lv référence le composant graphique
• findViewById
Android_ListView_Introduction17
Une activity, le modèle
• Le modèle itemsCC :– items d’un certificat de compétences constitué de 6 unités
• NFP121, RSX116, NSY102, SMB116, SMB117, UARS01– Unités enseignées au Cnam (présentiel et à distance)– Certificat de compétences intégrateur applications mobiles
– String[] itemsCC = …
Android_ListView_Introduction18
Une activity, choix de la stratégie d’affichage
• Stratégie : lv.setAdapter( new ArrayAdapter<String>(– Choix de la stratégie standard d’affichage
• this , le contexte• android.R.layout.simple_list_item_1, un texte par ligne, prédéfini• itemsCC, le modèle
Android_ListView_Introduction19
Exécution, le rendu
• Le rendu ici un item constitué d’un texte par ligne
Android_ListView_Introduction20
Une activity, choix de la stratégie d’affichage
• Le rendu : un item par liste– android.R.layout.simple_list_1 est prédéfini
• Serait-ce un TextView ?
Android_ListView_Introduction21
android.R.simple_list_item_1
• Un item de la liste est décrit ainsi– Standard …– <android-sdk>/platforms/<android-version>/data/res/layout/simple_list_item_1.xml
Android_ListView_Introduction22
http://developer.android.com/reference/android/R.html
• D’autres prédéfinis existent
Android_ListView_Introduction23
Sommaire-suite
• Vue– ListView
• Présentation
– Adapter la Vue d’une liste d’items aux souhaits du programmeur• Le patron Stratégie
– Utiliser des stratégies d’affichage standard
– Installer sa propre stratégie• Accès aux ressources décrites en XML
– Optimiser ces accès (cache), recyclage
– Filtrage, tri
• Contrôleur– View/Activity
• onItemClick, OnItemClickListener
– ListView/ListActivity• onListItemClick• onItemLongClick
Technique …– Chargement d’une liste et AsyncTask
Android_ListView_Introduction24
Un deuxième exemple
L’exemple précédent s’est enrichi
• Ajoutons pour chaque item– Une image pour la période d’enseignement
• 1er ou 2ème semestre– Le lieu d’enseignement en présentiel
• Prévoir que ce lieu puisse changer…
Android_ListView_Introduction25
Description xml, d’un item
Chaque item de la liste contient :– L’intitulé de l’unité– Une image suivie du lieu d’enseignement
• Le fichier res/layout/uecnam.xml– Décrit complètement cet item
Android_ListView_Introduction26
Description xml, d’une ligne
Chaque ligne contient :• L’intitulé de l’unité
– TextView
• Une image suivie du lieu d’enseignement
Android_ListView_Introduction27
Description xml, d’une ligne
Chaque ligne contient :• L’intitulé de l’unité• Une image suivie du lieu d’enseignement
– ImageView suivie TextView
Android_ListView_Introduction28
Le rendu attendu
• Stratégie à créer, il faut donc écrire notre propre Adapter– Notons que seules 5 unités, items, sont affichés ici
• Android a déclenché les 5 affichages correspondants• 5 appels de getView, getItem,… de la stratégie choisie
Android_ListView_Introduction29
Proposons maintenant notre propre Adapter
• Selon le patron Strategy, – Une classe implémentant l’interface ListAdapter
Aidons nous de l’existant …
• Il existe une sous classe qu’il suffit de dériver– BaseAdapter
• Il suffira de définir getCount, getItem, getItemId et getView• Nous l’appellerons UECnamAdapter
– Notre modèle a évolué• Ce n’est plus une simple table d’intitulés
– NFP121, RSX116, NSY102, SMB116, SMB117, UARS01
Android_ListView_Introduction30
Notre modèle a évolué
• Diplôme, UE deviennent des objets métiers
– Un diplôme est constitué d’unités d’enseignement (UE)• Chaque diplôme
– possède un intitulé et– délivre une liste de ses UE qui le compose
List<UE> getListe()
– Une UE est constituée • d’un intitulé,
– String getNom()• du lieu d’enseignement et
– String getLieu()• de la période
– String getPeriode()
Diplôme UE
Android_ListView_Introduction31
L’activité ne change guère, tjs quelques lignes
Proposons une stratégie concrète• UECnamAdapter
– Il ne nous reste plus qu’à définir les méthodes • getCount, getItem, getItemId et getView
Android_ListView_Introduction32
La classe UECnamAdapter
• Une stratégie concrète d’affichage des items• UECnamAdapter hérite de BaseAdapter
• Tout diplôme propose la liste des unités qui le compose– getCount, getItem, getItemId sont immédiats
Android_ListView_Introduction33
La classe UECnamAdapter, méthode getView
• Cette méthode est appelée par Android– À chaque affichage de la liste et seulement sur les lignes présentées
• Notre exemple présente 5 unités sur 6
–5 appels de getView
–getView la méthode
Android_ListView_Introduction34
La classe UECnamAdapter, méthode getView
• Pour chaque Item, nous avons
• getView algorithme :– Allons chercher le fichier XML défini pour l’UE (uecnam.xml)
– Réalisons l’adéquation• ListView / Modèle
– Ligne de la liste / UE du diplôme
• Affectons les items de chaque View avec certains attributs de l’UE
Android_ListView_Introduction35
Identifiants et affectation des champs
• Les identifiants issus du fichier XML– nomId– ImageId– lieuId
Android_ListView_Introduction36
La méthode getView
Allons chercher le fichier XML défini pour l’UE (res/layout/uecnam.xml)– LayoutInflater lecture du fichier XML
• Création de l’arbre Java
– Inflate( le fichier XML, la racine, booléen (complétion d’un arbre existant)
Android_ListView_Introduction37
La méthode getView
• Réalisons l’adéquation– ListView / Modèle
• Item de la liste / UE du diplôme
– Affectons les items de chaque View avec certains attributs de l’UE
Android_ListView_Introduction38
Prohibitif en temps d’exécution !
• Inflate transforme à la volée le fichier XML en arbre Java
– En version naïve cette transformation se produit à chaque appel• A chaque manipulation de l’utilisateur• A chaque affichage dans la partie visible de la liste• …
– Performance en temps d’exécution?
Idée :• Le système pourrait avoir déjà créé la vue, devenue
invisible … et pourrait tenter un recyclage
Android_ListView_Introduction39
Recyclage, performances
• Source http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/
Android_ListView_Introduction40
Recyclage de la vue d’un item
• Optimisation1. Le système a déjà créé la vue, dont il a conservé une référence
2. il tente un recyclage en transmettant cette référence
• La référence est transmise à la méthode getView
– Un contrat est en place• Si le paramètre convertView == null, la vue doit être créée
– Alors les liens sur les vues de la ligne sont conservées dans un cache
» Cache géré par le programmeur
• Sinon une référence de la vue est transmise et peut donc être utilisée– Nous utiliserons alors les éléments du cache
Android_ListView_Introduction41
Gestion du cache d’un item, déclaration
• Une classe interne et statique au sein de UECnamAdapter
• Ce cache d’un item constitué d’une instance de CacheView
• Cette instance est conservée dans un champ (tag) de la Vue de l’item • itemView.setTag (new CacheView(…)
Interne et statique sera préférée, attention aux classes internes et membres qui conservent une référence de l’instance englobante, référence engendrant parfois des fuites mémoires
Android_ListView_Introduction42
Gestion du cache, le contrat
• getView
alors la vue doit être créée
les références sur les vues de l’item sont installées dans un cache
sinon les références sont extraites du cache
Android_ListView_Introduction43
Initialisation du cache (convertView == null)
• Le champ tag d’une vue permet de mémoriser une référence
Android_ListView_Introduction44
C’est du recyclage, convertView != null
• Le champ tag d’une vue permet de mémoriser une référence (Ici le cache entre deux affichages)
• Le cache est utilisé
Android_ListView_Introduction45
Tri, filtrage
• La classe Adapter s’en charge
• Ou bien le modèle propose ce type de méthodes
• Ordre alphabétique des UE• Ordre en fonction de la période (1er ou 2ème semestre)
• Etc..
Android_ListView_Introduction46
En exemple de tri, ici selon le nom et la période
• Il suffit de proposer, selon les critères retenus– Une implémentation de l’interface Comparator entre deux UE
• Java tradition, cf. java.util.Collections
Android_ListView_Introduction47
Sommaire
• Vue– ListView
• Présentation
– Adapter la Vue d’une liste d’items aux souhaits du programmeur• Le patron Stratégie
– Utiliser des stratégies d’affichage standard– Installer sa propre stratégie
• Accès aux ressources décrites en XML– Optimiser ces accès (cache), recyclage
– Filtrage, tri
• Contrôleur– Le modèle a changé– View / Activity
• onItemClick, OnItemClickListener
– ListView / ListActivity• onListItemClick• onItemLongClick
Technique …– Chargement d’une liste et AsyncTask
Android_ListView_Introduction48
Le lieu d’enseignement change …
• Ce qui peut arriver, le modèle change– La vue est prévenue ….
– Changement du modèle• RSX116 est maintenant programmé en studio d’enregistrement en 17 2 6• Appel du mutateur, changement de lieu
– Appel de la méthode de l’adapter• ((BaseAdapter)lv.getAdapter()).notifyDataSetChanged();
– Adéquation par Android du modèle et de la vue
Réactualisation, appel(s) automatique(s) de getView
Android_ListView_Introduction49
Activity versus ListActivity
• Activity– Déclaration d’une ListView dans un fichier, recherche par l’identifiant
• ListView lv = (ListView) findViewById(R.id.liste)– Affectation de la stratégie d’affichage
• lv.setAdapter(new UeCnamAdapter( …– Affectation des écouteurs, aux items de la liste par le programme
• En général des instances de classes internes et membres– Pour chaque item de la liste, une instance d’une classe
» implements OnItemClickListener
• ListActivity– La déclaration est implicite
• Il doit exister une liste dont l’Id est @android:id/list– Affectation de la stratégie d’affichage, par une méthode
• setListAdapter(new UECnamAdapter( …– Affectation des écouteurs implicite
• Il suffit de redéfinir la méthode onListItemClick, redéfinie de la classe ListActivity
• Alors ListActivity nous préférerons
Android_ListView_Introduction50
Une classe dédiée ListActivity
• usage des ListView par une sous classe d’Activity : ListActivity• res/layout/liste.xml contient une ListView avec cet Id @android:id/list
ListeActivity
liste.xmlLa liste doitavoircet identifiant
Android_ListView_Introduction51
Contrôleur, ListActivity
• Au clic, contextuel– A chaque clic un toast est présenté, l’URL de l’UE est affiché
• À terme le site de l’unité pourrait être présenté …
– Méthode onListItemClick, redéfinie de la classe ListActivity
Android_ListView_Introduction52
A chaque clic, un Toast est affiché
• Ici un clic sur RSX116 affiche l’URL de l’unité• Une deuxième activité pourrait être exécutée
– Par exemple une WebView …
Android_ListView_Introduction53
Contrôleur, Activity et OnItemClickListener
• Une implémentation de OnItemClickListener
Android_ListView_Introduction54
Sommaire
• Vue– ListView
• Présentation
– Adapter la Vue d’une liste d’items aux souhaits du programmeur• Le patron Stratégie
– Utiliser des stratégies d’affichage standard– Installer sa propre stratégie
• Accès aux ressources décrites en XML– Optimiser ces accès (cache), recyclage
– Filtrage, tri
• Contrôleur– View/Activity
• onItemClick, OnItemClickListener
– ListView/ListActivity• onListItemClick• onItemLongClick
Technique …– Chargement d’une liste et AsyncTask– Chaque chargement d’item est en tâche de fond et utilise AsyncTask
Android_ListView_Introduction55
Rappel : schéma de programme, syntaxe, AsyncTask<Params, Progress, Result>
public void onStart(){ …
WorkAsyncTask wt = new WorkAsyncTask(); wt.execute(string1, string2, string3); … }
private class WorkAsyncTask extends AsyncTask<String,Long,Boolean>{
void onPreExecute() { // faire patienter l’utilisateur, affichage d’un sablier…
Boolean doInBackGround(String... t){ // effectuer la tâche coûteuse en temps // t[0]/string1, t[1]/string2,…
void onProgressUpdate(Long... v) { // informer l’utilisateur que le traitement est en cours
void onPostExecute(Boolean b) { // le sablier disparaît, une éventuelle erreur est affichée
}
Android_ListView_Introduction56
Chargement des items d’une liste et AsyncTask
• Si le chargement des items d’une liste devient coûteux en temps d’exécution
Alors ce chargement pourrait être effectué en tache de fond
• Construction de la liste item par item en tâche de fond– Usage de AsyncTask
– Reprenons le premier exemple …
Android_ListView_Introduction57
Une exemple d’usage d’AsyncTask
• ConstructionListe extends AsyncTask– ArrayAdapter contient une liste vide,
• Celle-ci sera affectée en tache de fond
Android_ListView_Introduction58
ConstructionListe extends AsyncTask
Construction de la liste en tache de fond …
Android_ListView_Introduction59
Le chargement de la liste nécessite une requête sur le web : encore AsyncTask
private class ChargeurDeLaListe extends AsyncTask<URL, Void, Boolean>{ ProgressDialog dialog
void onPreExecute() { dialog = ProgressDialog( // …
Boolean doInBackGround(URL... t){ UneListe = Résultat d’une Requete en URL[0]…
void onPostExecute(Boolean b) { Affecter UneListe selon la stratégie ou bien prévenir si échec dialog.dissmiss();}
Android_ListView_Introduction60
Chargement d’un item d’une liste et AsyncTask
• Si le chargement d’un item d’une liste devient coûteux en temps d’exécution
– Usage de AsyncTask
• Source http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/
Android_ListView_Introduction61
Source http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/
Android_ListView_Introduction62
CursorAdapter et les contacts
• http://www.java2s.com/Code/Android/UI/UsingSimpleCursorAdapter.htm
• Autre support …
Android_ListView_Introduction63
Sauvegarde / restitution du modèle
• Par exemple entre deux rotations de l’écran…
• Une solution
– Classe interne et statique + Variable de classe
– Soit : Une zone mémoire de la DVM, indépendante du cycle de vie de l’activité
– Nous préférerons un service
• très inspiré de http://www.vogella.de/articles/AndroidPerformance/article.html
Android_ListView_Introduction64
A la création
public class ListeActivity extends ListActivity {
private static Modèle modèle;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// restitution éventuelle modèle = (Modèle) getLastNonConfigurationInstance();
}
Android_ListView_Introduction65
Démarrage et Sauvegarde au cas où
@Override public Object onRetainNonConfigurationInstance() {
return modèle;
}
À lire :
http://www.yousaytoo.com/retrieve-old-activity-state-for-configuration-change-by-overriding-onre/3600379