Android SimpleCursorAdapter sélection de données

Dans notre désormais préféré OS mobile, nous voudrions sélectionner des données sur un écran, à partir d’une source de données à nous. Par exemple.

Nous avons déjà construit un ContentProvider (enfin à priori).
Nous allons lier le contenu de ce ContentProvider avec un élément de présentation, en l’occurence, un Spinner.
Tout ça n’est pas très complexe, mais il y a quelques subtilités.

L’avantage de cette petite présentation est l’utilisation de données entre applications, l’utilisation des ressources et la manipulation de l’interface.

Le ContentProvider

Tout d’abord, nous avons une application qui fournit un contenu sous forme d’un ContentProvider. C’est une classe qui hérite de ContentProvider et qui définit une URI pour y accéder.
Nous passons sur les étapes de création de cette classe, voici l’URI qui donne accès aux données :

content://com.oxiane.provider.Livres/livres

Les champs de notre modèle sont les suivants (ce code fait partie de la classe LivreProvider par exemple ici) :

public static final String _ID = "_id";
public static final String TITLE = "title";
public static final String BODY = "body";

Notre Layout

Il est très simple et ne contient qu’un champ texte et un Spinner :

    
    

Notre Activity

Nous passons à l’activity, une activity normale, toute simple, pas besoin de ListActivity ou autre.
Déclaration du cursor et du Spinner (liste déroulante) qu va accueillir les données :

Uri uriLivres = Uri.parse("content://com.oxiane.provider.Livres/livres");
Cursor curAll = managedQuery(uriLivres, null, null, null, "title asc");

Spinner spinner = (Spinner) findViewById(R.id.spinner);

Le Spinner va être lié au cursor de façon simple :

SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
android.R.layout.simple_spinner_item, curAll,
new String[] { "title" }, new int[] { android.R.id.text1 });

Ici, nous avons utilisé des éléments de layout fournis par android, dont celui dédié à un Spinner, nous aurions pu créer nos propres éléments, mais c’est un autre sujet. Le champ « title » est une valeur texte qui correspond au champ de notre classe ContentProvider. Le dernier paramètre de l’appel représente un champ texte par défaut (en tout cas sa représentation en terme d’ID de layout android).

Ensuite on ajoute la ressource de Layout (encore une fois une ressource par défaut) pour notre adapter, enfin on associe le Spinner à l’Adapter :

adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);

Le listener

La dernière étape consiste à ajouter un listener. Si notre Spinner avait été associé à un ArrayAdapter par exemple, nous aurions eu un code de ce type :

spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
	public void onItemSelected(AdapterView parent, View view, int position, long id) {
		Toast.makeText(parent.getContext(),
			">> : " + parent.getItemAtPosition(p).toString(), Toast.LENGTH_SHORT).show();
	}
	public void onNothingSelected(AdapterView arg0) {
		// rien du tout
	}
});

Mais parce que nous avons alimenté notre Spinner avec un Cursor (bio et végétarien), il faut faire une petite manipulation :

spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
	public void onItemSelected(AdapterView parent, View view, int position, long id) {
		Toast.makeText(parent.getContext(),
			">> : " + ((Cursor) parent.getItemAtPosition(p)).getString(1), 
				Toast.LENGTH_SHORT).show();
	}
	public void onNothingSelected(AdapterView arg0) {
		// rien du tout
	}
});

et hop

L’utilisation de la méthode getString(1) est bien entendue liée au Cursor que nous interrogeons, c’est à dire le champ d’index 1, et ici, c’est le champ « title » de type String.
Sans cette petite manipulation, on risque de récupérer un bidule de ce type : android.content.ContentResolver$CursorWrapperInner@176276
et ça, c’est pas vraiment bio !

Je fais juste une petite vérification avec mon shell adb pour aller voir mes données qui sont si jolies :

shell adb
# cd data/data
# cd com.oxiane.mon_appli
# cd databases
# ls

Livres
# sqlite3 Livres
SQLite version 3.5.9
Enter ".help" for instructions
sqlite> .tables
.tables
android_metadata  titles
sqlite> select * from titles;
select * from titles;
7|zshell_01|z data 01
8|zshell_02|z data 02
9|ashell_02|a data 02
10|ashell_01|a data 01
11|ashell_001|a data 001
sqlite>

Tout est nickel !

La base de cet article est sur le site d’android : binding data

La formation Android chez OXiane

Alain