Nous allons dans ce tutoriel voir comment optimiser une liste déroulante afin d’en améliorer la performance et nous verrons comment ajouter un filtre sur une liste qui permettra à l’utilisateur de rechercher l’élément qu’il souhaite afficher. 

  Un exemple de liste avec filtre :

 


Optimisation de la liste déroulante ou le recyclage des items :

 

Un solution d’optimisation d’une liste déroulante comme celle-ci est le recyclage des éléments de la liste.

Même si la liste contient plusieurs éléments, elle ne peut parfois pas tous les afficher si on ne scroll pas, les éléments les plus utiles sont ceux qui sont visibles !

Le principe est simple, à chaque fois qu’une ligne sort de l’écran, nous la recyclons et l’affectons au prochain élément de la liste.

 

Un schéma vaut parfois mieux que des explications ! Voilà qui devrait vous aider à comprendre le principe du recyclage !

 

 

Nous allons maintenant voir comment modéliser tout ça au niveau de nos classes,

 


Modélisation :

 

 

 

La liste déroulante est obtenue grâce à la classe ListView.

Les données de la liste et le layout à utiliser pour les éléments de la liste sont définies par l’adapter.

Pour notre exemple, nous allons définir un CustomAdapter qui va hériter d’un ArrayAdapter ( il en existe d’autres mais nous utiliserons celui-là ).

A chaque ligne de la liste, une méthode getView() sera appelée. A chaque appel, une vue composée de deux vues ( ImageView et Textview ) sera générée.

Toutefois la création d’un objet est coûteux en performance, il faudra donc redéfinir cette méthode pour optimiser la liste ! Notre astuce consistera donc à garder en mémoire la vue sortante et de la recycler comme l’illustre le schéma plus haut.

La vue qu’on souhaite recycler est envoyé en paramètre de la méthode getView en tant que convertView.

Il suffit juste de remplacer son contenu avec le nouveau. On éviter ainsi de créer une nouvelle vue. Un test de nullité doit être effectué sur convertView car ce dernier peut être null.

L’utilisation de la classe static ViewHolder va nous apporter une amélioration supplémentaire. En effet, même si les vues sont recyclés, il faut tout de même récupérer chaque élément de la vue ( ImageView et TextView ) avec la méthode findViewById. L’appel à cette méthode est très couteux en performance. Mais grâce à ViewHolder, chaque vue sera référenciée avec la méthode setTag. On peut donc récupérer les vues des éléments recyclées avec la méthode getTag de la classe ViewHolder, on n’a donc pas recours à la méthode findViewById !

Pour pouvoir filtrer la liste, nous alloons mettre un listener sur notre EditText. L’adapter sera notifié à chaque changement de contenu de l’EditText, la méthode filter() de l’adapter sera appelée.

Bon assez parlé, maintenant place à l’implémentation de tout ça !

 

 

 Implémentation :

 

Le main.xml

c’est ici qu’on déclare nos vues

main.xml
<EditText    android:id="@+id/filtre"    android:layout_width="fill_parent"    android:layout_height="wrap_content"/>      <ListView    android:id="@+id/list"    android:layout_width="fill_parent"    android:layout_height="wrap_content" />

 

Le listitem.xml

on définit les vues contenues dans un élément de la liste

Listitem.xml
<ImageView    android:id="@+id/icon"    android:layout_width="50px"    android:layout_height="50px"    android:layout_marginLeft="4px"    android:layout_marginRight="10px"    android:layout_marginTop="4px" >    </ImageView>        <TextView    android:id="@+id/nom" android:gravity="center"    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:textSize="20px" >    </TextView>

 

L’activité principale

 C’est ici que toutes les classes dont nous avons besoin seronts instanciées

Activité principale
adapter = new CustomAdapter(this, Listnoms);    listView = (ListView) findViewById(R.id.list);    listView.setAdapter(adapter);     listView.setTextFilterEnabled(true);      EditText filterEditText = (EditText) findViewById(R.id.filtre);    filterEditText.addTextChangedListener(new TextWatcher() {    @Override    public void onTextChanged(CharSequence s, int start, int before,    int count) {     }    @Override    public void beforeTextChanged(CharSequence s, int start, int count,    int after) {    }    @Override    public void afterTextChanged(Editable s) {    adapter.getFilter().filter(s.toString());     }    });

 

 

Le customAdapter

Cette classe contient toutes les méthodes nécessaires pour le recyclage de vue, les méthodes de ViewHolder qui évite qu’on crée un nouvel élément à chaque fois qu’on navigue dans la liste et le filtre.

CustomAdapter
private final Activity context;    List<String> arrayList;     List<String> listeNom;      static class ViewHolder {    public TextView text;    public ImageView image;    }      public CustomAdapter(Activity context, List<String> listeNom) {    super(context, R.layout.listitem, listeNom);    this.context = context;    this.listeNom = listeNom;    this.arrayList= listeNom;    }      @Override    public View getView(int position, View convertView, ViewGroup parent) {    View rowView = convertView;    if (rowView == null) {    LayoutInflater inflater = context.getLayoutInflater();    rowView = inflater.inflate(R.layout.listitem, null);    ViewHolder viewHolder = new ViewHolder();    viewHolder.text = (TextView) rowView.findViewById(R.id.nom);    viewHolder.image = (ImageView) rowView    .findViewById(R.id.icon);    rowView.setTag(viewHolder);    }      ViewHolder holder = (ViewHolder) rowView.getTag();    String s = listeNom.get(position);    holder.text.setText(s);    holder.image.setImageResource(R.drawable.ic_launcher);    return rowView;    }    @Override    public int getCount() {    return listeNom.size();    }        @Override    public String getItem(int position) {    return listeNom.get(position);    }      @Override    public Filter getFilter() {    return new Filter() {      @SuppressWarnings("unchecked")    @Override    protected void publishResults(CharSequence constraint, FilterResults results) {    listeNom = (ArrayList<String>) results.values;    CustomAdapter.this.notifyDataSetChanged();    }    @Override    protected FilterResults performFiltering(CharSequence constraint) {    ArrayList<String> filteredResults = getFilteredResults(constraint);    FilterResults results = new FilterResults();    results.values = filteredResults;    return results;    }    private ArrayList<String> getFilteredResults(CharSequence constraint) {    ArrayList<String> filteredTeams = new ArrayList<String>();    for(int i=0;i< arrayList.size();i++){    if(arrayList.get(i).toLowerCase().startsWith(constraint.toString().toLowerCase())){    filteredTeams.add(arrayList.get(i));    }    }    return filteredTeams;    }    };    }

 

Et c’est ainsi que s’achève notre tuto sur l’optimisation de liste ! Bonne implémentation à tous et n’oubliez pas de VOTER et de PARTAGER cet article! 

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.