Android View, onClick, Activity,
Modèle Vue Contrôleur
jean-michel Douin, douin au cnam point fr
version : 5 Mai 2014
Notes de cours
1
Android_MVC
Bibliographie utilisée
http://developer.android.com/resources/index.html
…
Android : Développer des applications mobiles pour les Google Phones,
de Florent Garin, chez Dunod
Le cours de Victor Matos
http://grail.cba.csuohio.edu/~matos/notes/cis-493/Android-Syllabus.pdf
Android A Programmers Guide - McGraw Hill
Professional Android Application Development – Wrox
http://marakana.com/bookshelf/main_building_blocks_tutorial/table_of_contents.html
2
Android_MVC
Avertissement, pré-requis et sommaire
• Pré requis indispensable
– Avoir réalisé le tp mvc,
– Un tp utilisant une calculette à pile
• Au sommaire
– Comment assurer un couplage faible des classes
– Observable/Observateur
– IHM/Vue et Listener/Contrôleur
3
Android_MVC
Pré requis, rappel
• Pré requis
– TP Calculette à pile déjà réalisé J2SE
• Thème : Modèle Vue Contrôleur
• http://jfod.cnam.fr/eicnam/tp_mvc/tp_mvc.html
– Usage de l’applette à cette URL est conseillée
>appletviewer http://jfod.cnam.fr/eicnam/tp_mvc/tp_mvc.html
4
Android_MVC
Pré requis, MVC
• http://java.sun.com/blueprints/guidelines/designing_enterprise_applications/introduction/summary/index.html
5
Android_MVC
Pré requis, l’architecture retenue pour le TP
• Le Modèle est une pile (classe PileModele<T>).
• La Vue correspond à l'affichage de l'état de la pile (classe Vue).
• Le Contrôleur gère les évènements issus des boutons +, -, *, /,[] (classe Controleur).
– L'applette crée, assemble le modèle, la vue et le contrôle (classe AppletteCalculette).
6
Android_MVC
Cette architecture engendre des discussions
• Le Modèle est ici une pile (classe PileModele<T>).
• La Vue correspond à l'affichage de l'état de la pile (classe Vue).
• Le Contrôleur gère les évènements issus des boutons +, -, *, /,[]
– L'applette crée, assemble le modèle, la vue et le contrôle (classe AppletteCalculette).
7
Android_MVC
Discussions … entre nous
• Le modèle pourrait être la calculette constituée pour ses
calculs internes d'une pile,
• Pourquoi les "listeners" des boutons sont-ils locaux au
contrôleur ?
• Pourquoi un JPanel pour le contrôleur ?
• Ce choix de découpage MVC vous parait-il réaliste ?
– Discussion, blabla, blabla, blabla
8
Android_MVC
Architecture classique … une valeur sûre
L’utilisateur
L’utilisateur
clique
visualise
• Ici le Modèle hérite de java.util.Observable
• La Vue implemente java.util.Observer
9
Android_MVC
MVC encore
• Model extends Observable
• View implements Observer
• Controller implements XXXXListener, YYYYListener
10
Android_MVC
Nouvelle architecture
En conséquence
Au tp
• Le Modèle est une pile (classe PileModele<T>).
• La Vue correspond à l'affichage de l'état de la pile (classe Vue).
• Le Contrôleur gère les évènements issus des boutons +, -, *, /,[].
Architecture retenue
• Le Modèle est une calculette
• La Vue correspond à l’IHM (au complet).
• Le Contrôleur gère les évènements issus des boutons +, -, *, /,[]
11
Android_MVC
Architecture retenue
• Le Modèle
– La calculette munie de ses opérations (+,-,/,*,…)
• Hérite de la classe java.util.Observable
• Les sources du modèle sont ici
– http://douin.free.fr/tp4Calculette/
• La Vue
– L’IHM affichage, zone de saisie, boutons …
• Implémente java.util.Observer
• Le Contrôleur
– Réalisation, implémentation des listeners, (le comportement de l’IHM)
• Implémente plusieurs ActionListener
-> pour Android, quel découpage ?, quelles classes ?
12
Android_MVC
Android, la classe Activity
• Activité comme application élémentaire
– À cette activité lui correspond une IHM, ce que l’on voit …
public class Calculette extends Activity {
– Cette IHM est décrite par un fichier XML (la vue)
– L’activité réagit aux sollicitations de l’utilisateur (le contrôleur)
13
Android_MVC
L’IHM de la calculette
• Un fichier XML décrit complètement cette interface
• L’activité Calculette affiche, présente cette interface
14
Android_MVC
Android, la calculette
• L’activité affiche l’IHM
• Le modèle ne change pas
– Cf. le TP
• Android : Démonstration …
15
Android_MVC
IHM : Layout, View , Button…
LinearLayout
TextView
EditText
TableRow
Button
ProgressBar
• Description de cette interface en XML
– Fichier res/layout/main.xml
16
Android_MVC
Interface, IHM : Approche déclarative ./res/
• Chaque composant possède un id (android:id= "@+id/push")
17
Android_MVC
Chaque composant a son id
etatPile
donnee
TableRow
clear
plus sub div
jauge push mul
• <Button android:id="@+id/push"
18
Android_MVC
IHM, un outil de conception sous eclipse
• Item comme classe
– Nom de la balise
comme
– Nom de la classe
• Properties de chaque item
– Attribut XML, cf. Properties
comme
– Mais aussi comme Attribut de la classe,
19
Android_MVC
Adéquation XML <-> java, le fichier R
• En XML
• <EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="true"
android:visibility="visible"
android:clickable="false"
android:layout_margin="5dip"
android:numeric= "decimal"
android:inputType= "number"
android:id="@+id/donnee"
android:text="1" />
…
<Button android:id="@+id/push"
En Java
EditText donnee = (EditText) findViewById(R.id.donnee);
Button empiler = (Button) findViewById (R.id.push);
20
Android_MVC
Intégration de l’IHM, R.layout.main
• Au sein d’une Activity
– XML : accès en java via R
• Les ressources XML sont accessibles via le fichier R
• R.java est généré par Android
• Convention : /layout/main -> R.layout.main, R.id. R.string. …
»R cf. dossier /gen/
21
Android_MVC
Intégration de l’IHM, R.layout.main
• Au sein d’une Activity
– Au préalable l’affectation de l’interface par l’appel de
– setContentView(R.layout.main);
– Les composants de l’IHM deviennent accessibles
• Button empiler = (Button) findViewById(R.id.push);
– findViewById est une méthode héritée de la classe Activity
– Le source java ne manquera pas de R, ni d’appels de R (facile …)
22
Android_MVC
Une Activity, « démarrage » par onCreate
public class TPCalculette extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Affectation de l’IHM issue des fichiers XML
setContentView(R.layout.main);
23
Android_MVC
Une Activity accès aux composants
public class TPCalculette extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// accès aux composants de l’IHM
Button empiler = (Button) findViewById(R.id.push);
ProgressBar jauge = (ProgressBar) findViewById(R.id.jauge);
// accès aux chaînes de caractères ( plusieurs langues)
String str = getString(R.string.app_name);
24
Android_MVC
Comportement : OnClickListener et plus
• Un seul « Listener » par composant
• Button empiler = (Button) findViewById(R.id.push);
empiler.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
// traitement associé
}
}
25
Android_MVC
Ou bien usage de l’Attribut onClick
• Extrait de layout/main.xml
• <Button android:layout_height="wrap_content" android:id="@+id/push"
• android:layout_width="wrap_content"
android:text="@string/push"
• android:onClick="onClickEmpiler">
• </Button>
• Dans la classe de l’activity
public void onClickEmpiler(View v){
// traitement associé
}
26
Android_MVC
Démonstration
Une démonstration
• Avec au moins un bouton … de bienvenue
– À chaque clic la chaîne hello world est modifiée
27
Android_MVC
Android : la description de l’application
• Description de l’application
– Quelles activités ?
• Plusieurs activités pour une application
– Quelles permissions ?
• SMS, Réseau, GPS, …
– Quelles librairies ?
• Dans un fichier XML
– AndroidManifest.xml
28
Android_MVC
AndroidManifest.xml, tp4Calculette
• La description de l’application,
– destinée à l’hébergeur
29
Android_MVC
MVC et Android
• Nous avons :
– Une IHM décrite en XML
– Une activité qui implémente le comportement
• Alors
– L’activité est le contrôleur de la vue, de l’IHM décrite en XML
– L’activité met l’IHM au premier plan,
• l’activité a accès aux composants graphiques
• MVC ?
– Le modèle est une calculette
– La vue du modèle est l’activité
30
Android_MVC
MVC, Mise en Pratique : discussions
extends java.util.Observable
Calculette implements CalculetteI
Modèle
update(.. enter, add, sub, …
Activity extends Activity
implements java.util.Observer
« XML » Contrôleur
IHM Listeners
• L’activity Android est une vue du Modèle Calculette (implements Observer)
• L’activity Android est le contrôleur de l’IHM décrite en XML (extends Activity)
31
Android_MVC
packages
mode
modèle
32
Android_MVC
Le Modèle : la Calculette
public interface CalculetteI {
// operations
void enter(int i) throws CalculetteException;
void add() throws CalculetteException;
void sub() throws CalculetteException;
void div() throws CalculetteException;
void mul() throws CalculetteException;
void clear();
int pop() throws CalculetteException;
// interrogations
int result() throws CalculetteException;
boolean isEmpty();
boolean isFull();
int size();
int capacity();
}
public class Calculette
extends java.util.Observable
implements CalculetteI
33
Android_MVC
TP4CalculetteActivity,
la vue du modèle + le Contrôleur de l’IHM
public class Tp4CalculetteActivity extends Activity implements Observer{
private Calculette calculette;
public void onCreate(Bundle savedInstanceState) { // appelée par Android
super.onCreate(savedInstanceState);
this.calculette = new Calculette(); // une calculette est créée
this.calculette.addObserver(this); // c’est une vue du modèle calculette
setContentView(R.layout.main); // l’IHM est associée à cette activité
….
}
…
public void onClickEmpiler(View v){ // attribut onClick balise <Button
}
…
public void update(Observable arg0, Object arg1) { // à chaque notification
}
34
Android_MVC
TP4CalculetteActivity,
le Contrôleur de l’IHM
public class Tp4CalculetteActivity extends Activity implements Observer{
private Calculette calculette;
public void onCreate(Bundle savedInstanceState) { // appelée par Android
…
….
}
…
public void onClickEmpiler(View v){ // attribut onClick balise <Button
try{
int operande = …
this.calculette.empiler(operande); // opération empiler sur le modèle
}catch(CalculetteException nfe){}
}
public void onClickAdd(View v){
…
public void update(Observable arg0, Object arg1) { // à chaque notification
}
35
Android_MVC
TP4CalculetteActivity,
est une vue du modèle
public class Tp4CalculetteActivity extends Activity implements Observer{
private Calculette calculette;
public void onCreate(Bundle savedInstanceState) { // appelée par Android
….
}
…
public void onClickEmpiler(View v){ // attribut onClick
}
public void update(Observable arg0, Object arg1) { // à chaque notification du
TextView etat = (TextView) findViewById(R.id.etatPile); // modèle
etat.setText(calculette.toString());
ProgressBar jauge = (ProgressBar) findViewById(R.id.jauge);
jauge.setProgress(calculette.size());
actualiserInterface();
}
36
Android_MVC
Architecture retenue
• Application Calculette en résumé
– Observable : Le modèle, la calculette
– Observer : l’Activity, mise à jour de l’interface
– View : le fichier XML (l’IHM)
– Controller : l’Activity
37
Android_MVC
Android, la calculette
• Discussion, réalisation …
38
Android_MVC
Android et MVC, discussion
extends java.util.Observable
Calculette implements CalculetteI
Modèle
update(.. enter, add, sub, …
Activity extends Activity
implements java.util.Observer
« XML » Contrôleur
IHM Listeners
public class CalculetteActivity
extends Activity
implements Observer{
39
Android_MVC
Comportements attendus, cycle de vie
• 3 + 2 == 5 ?
• Appui sur la touche « retour »
– Fin de l’activité
• Appui sur la touche « HOME »
– L’activité est en Pause …
• Pendant que je calcule 3 + 2, je reçois un urgent appel téléphonique
– telnet localhost 5554
– gsm call 5554
• Une rotation de l’écran a lieu
• http://developer.android.com/guide/developing/tools/emulator.html
– Ctrl-F11, Ctrl-F12
40
Android_MVC
Cycle de vie d’une activity, je calcule
• ….
41
Android_MVC
Cycle de vie d’une activity, j’ai fini
• ….
42
Android_MVC
Cycle de vie d’une activity, je lance une autre activity
• ….
43
Android_MVC
Cycle de vie d’une activity, je calcule de nouveau
• ….
44
Android_MVC
Cycle de vie d’une activity, un appel urgent
telnet localhost 5554
gsm call 5554
• ….
45
Android_MVC
Cycle de vie d’une activity, je réponds
• ….
46
Android_MVC
Cycle de vie d’une activity, je raccroche
• ….
47
Android_MVC
Illustration du cycle de vie
• Illustration du cycle de vie
– Démonstration
• Touche « Retour »
– onPause, onDestroy ….ok
• Touche Menu
– onSaveInstanceState, onPause, onStop ...ok
– Sauvegarde par défaut …
• Un appel idem
• Rotation de l’écran Ctrl-F11, Ctrl-F12
– … !!!
• Android détruit votre vue en cas de rotation pour construire la nouvelle vue
48
Android_MVC
Cycle de vie d’une activity, onSaveInstanceState
• ….
49
Android_MVC
Cycle de vie d’une activity, onRestoreInstanceState
• ….
50
Android_MVC
Mise en Pratique, suite
– Suite du TP :
• Sauvegarde de l’état de la calculette
• Cf. cycle de vie
protected void onSaveInstanceState(Bundle out){
out.putInt("taille",calculette.size());
…
protected void onRestoreInstanceState(Bundle in){
int taille = in.getInt("taille");
…
– Sauvegarde et restitution via le bundle
• http://developer.android.com/reference/android/os/Bundle.html
51
Android_MVC
Cycle de vie d’une activity …
• http://www.itcsolutions.eu/wp-content/uploads/2011/08/Android_Activity_Events-Copy.png
52
Android_MVC
Illustration du cycle de vie
• Ecran de veille alors que la calculette était au premier plan
– onPause
– Noté semi-visible dans la biblio …
53
Android_MVC
Cycle de vie d’une activity, écran de veille, touche F7
• ….
54
Android_MVC
Cycle de vie d’une activity, au réveil, touche F7
• ….
55
Android_MVC
Un extra pour la calculette
• A chaque mauvais format du nombre, un sms est envoyé !
– Une exception Over The Air …
– 1) l’activité Calculette envoie le SMS
SmsManager sm = SmsManager.getDefault();
• Si j’ai la permission
– 2) L’activité standard d’envoi de SMS est appelée
• Intent sendIntent = new Intent(Intent.ACTION_VIEW);
• startActivity(sendIntent);
56
Android_MVC
Au sein de votre application
private void sendSMS(String msg){
try{
SmsManager sm = SmsManager.getDefault();
String body = getString(R.string.app_name) + " : " + msg + "\n";
sm.sendTextMessage(getString(R.string.numero_tel), null, body,
null, null);
// ou bien un Toast
Toast.makeText(getBaseContext(),
" envoi d’un sms " + msg, Toast.LENGTH_LONG).show();
}catch(Exception e){
Toast.makeText(getBaseContext(), getString(R.string.erreur),
Toast.LENGTH_LONG).show();
}
}
• Mais avez-vous la permission ?, -> AndroidManifest
57
Android_MVC
Une Activity en démarre une autre
• Intent
ou comment transmettre des paramètres à une activité
• Intent sendIntent = new Intent(Intent.ACTION_VIEW);
• sendIntent.putExtra("sms_body", "The SMS text");
• sendIntent.setType("vnd.android-dir/mms-sms");
• startActivity(sendIntent);
• Une pile d’activité en interne
• Cycle de vie
58
Android_MVC
Cycle de vie d’une activity, startActivity(sendIntent);
• ….
59
Android_MVC
Cycle de vie d’une activity, sms envoyé +
• ….
60
Android_MVC
Quelques remarques
• Attention à la persistance
• Lorsque l’activité est en Pause ou Stoppée
– Android peut décider de supprimer l’activité
61
Android_MVC
Cycle de vie d’une activity, android killer
• ….
62
Android_MVC
Cycle de vie d’une activity, android killer
63
Android_MVC
L’architecture se précise
• Une Activity peut en déclencher une autre
– A chaque activity son écran (son fichier XML)
– Nécessaire gestion de ces activités, android utilise une pile
64
Android_MVC
Extension possible : à chaque exception un sms !
• Trop de sms ….
• Un mauvais format de Nombre Contrôle de la saisie
android:numeric="decimal"
android:inputType="number"
65
Android_MVC
La pile des Activity
• http://www.vineetgupta.com/2011/03/mobile-platforms-part-1-android/
• http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html
66
Android_MVC
Annexe : un tutorial
• http://www.itcsolutions.eu/2011/08/26/android-tutorial-
overview-and-contents/
• http://www.itcsolutions.eu/2011/08/27/android-tutorial-4-
procedural-vs-declarative-design-of-user-interfaces/
67
Android_MVC
• http://good-good-study.appspot.com/blog/posts/103001
68
Android_MVC
• http://www.itcsolutions.eu/2011/08/27/android-tutorial-4-procedural-vs-declarative-design-of-user-interfaces/
69
Android_MVC
70
Android_MVC
Vocable
71
Android_MVC
Vocable
72
Android_MVC