Utiliser une classe interne comme auditeur

Nous pouvons définir une autre classe qui est imbriquée dans MainActivity et qui peut servir d’objet d’audience (Listing 5-13). Java permet aux classes d'être imbriquées, nous allons donc en tirer parti; Il existe quelques règles à respecter lors de la définition d’une classe interne, et nous en discuterons dès qu’elles deviennent nécessaires.

Listing 5-13. Une classe intérieure dans MainActivity

 

  1. public class MainActivity extends AppCompatActivity {
  2.  
  3. @Override
  4.  
  5. protected void onCreate(Bundle savedInstanceState) { . . . }
  6.  
  7. private class ButtonHandler implements View.OnClickListener {
  8.  
  9. }
  10. }
  11.  
  12.  

Cette ligne montre la méthode onCreate en mode plié. Les capacités de pliage de code de AS3 sont très utiles lorsque vous travaillez avec beaucoup de codes; il réduit l'éditeur principal et vous aide à vous concentrerNotre classe interne telle qu'elle se trouve dans MainActivity. Nous l’avons définie comme privée car elle n’a pas besoin d’être visible de l’extérieur de MainActivity. La même chose que notre classe anonyme dans les sections précédentes, cela doit aussi implémenter l'interface View.OnClickListener car nous allons l'utiliser comme écouteur pour les clics sur les boutons 

Remarque : Il est possible que des avertissements et des erreurs apparaissent sur AS3 lors de l'ajout du code de gestion des événements. Ce sont très probablement des déclarations d'importation manquantes; Passez simplement votre souris sur les lignes sinueuses et utilisez la solution rapide (Option + Entrée pour macOS | Alt + Entrée pour Windows et Linux). Il faut importer tous les packages nécessaires.

Listing 5-14. Implémentation de ButtonHandler

 

  1. private class ButtonHandler implements View.OnClickListener {
  2.  
  3. @Override
  4.  
  5. public void onClick(View view) {
  6.  
  7. switch (view.getId()){
  8.  
  9. case R.id.button1:
  10. show("Button One");
  11.  
  12. break;
  13. case R.id.button2:show("Button Two");
  14.  
  15. break;
  16. case R.id.button3:
  17. show("Button Three”);
  18.  
  19. break;
  20. default:show("This should not happen");
  21.  
  22. }
  23. }
  24. }

Overr Nous remplaçons la méthode onClick de View.OnClickListener; lorsque l'on clique sur l'un des trois boutons, cette méthode est appelée, comme dans notre code de classe anonyme des sections précédentes. Le moteur d'exécution remplira le paramètre View avec la référence à l'objet du bouton sur lequel l'utilisateur a cliqué. C’est ce que nous allons utiliser pour identifier le bouton sur lequel on a cliqué avec la classe Android Toast.La méthode getId de l'objet View renvoie une valeur entière qui correspond à l'ID du bouton tel qu'il est défini dans la classe R.class. N'oubliez pas que les fichiers de présentation sont gonflés pendant l'exécution afin de générer les objets Java réels correspondant à l'élément View décrit dans la présentation. Le runtime génère la classe R., que nous pouvons utiliser pour faire référence par programme aux objets définis dans le fichier de présentationNous vérifions simplement si la valeur de view.getId est l’un de nos boutons; dans cette ligne, nous vérifions s’il s’agit bien de R.id.button1Si vous avez cliqué sur button1, nous appelons une méthode appelée show () et lui passons une chaîne. Nous n'avons pas encore défini la méthode show 

Listing 5-15. show( ) Method

void show(String message) {

  Toast.makeText(this, message, Toast.LENGTH_LONG).show();

   Log.i(getClass().getName(), message);                     }

Nous affichons un message Toast. Toast fournit une petite rétroaction sous la forme d'une petite fenêtre contextuelle. Il apparaît comme une superposition dans l’activité en cours, et son apparence n’est que pour une certaine durée, de sorte qu’elle ne masque pas l’activité en cours. C’est un moyen discret d’afficher le statutmessagesLa classe Log nous permet de créer des entrées de journal à peu près comme System.out.println, mais il est plus approprié d'utiliser la classe Log pour générer des messages de débogage et de diagnostic. Vous pouvez afficher les entrées de journal créées par la classe Log dans la fenêtre de l'outil Logcat.La méthode show (Listing 5-15) est membre de MainActivity. ButtonHandler a accès aux méthodes (ou variables) définies dans sa classe englobante. Nous aurions pu définir cette méthode dans la classe ButtonHandler, ce qui aurait été bien aussi. 

Figure 5-11. Toast message

 Complete code for MainActivity is found in Listing 5-16.

Listing 5-16. Complete Code for MainActivity

 

  1. package com.example.ted.eventhandling1;
  2.  
  3. import android.support.v7.app.AppCompatActivity;
  4. import android.os.Bundle;
  5. import android.util.Log;
  6. import android.view.View;
  7. import android.widget.Toast;
  8. public class MainActivity extends AppCompatActivity {
  9.  
  10. @Override
  11.  
  12. protected void onCreate(Bundle savedInstanceState) {
  13.  
  14. super.onCreate(savedInstanceState);
  15. setContentView(R.layout.activity_main);
  16.  
  17. ButtonHandler bh = new ButtonHandler();
  18. findViewById(R.id.button1).setOnClickListener(bh);
  19. findViewById(R.id.button2).setOnClickListener(bh);
  20. findViewById(R.id.button3).setOnClickListener(bh); }
  21. private class ButtonHandler implements View.OnClickListener {
  22.  
  23. @Override
  24.  
  25. public void onClick(View view) {
  26. switch (view.getId()){
  27. case R.id.button1:show("Button One");
  28. break;
  29. case R.id.button2:show("Button Two");
  30. break;
  31. case R.id.button3:show("Button 3");
  32. break;
  33. default:
  34.  
  35. show("This should not happen"); }
  36. }
  37. }
  38. }
  39.  
  40. void show(String message) {
  41.  
  42. Toast.makeText(this,message,Toast.LENGTH_LONG).show();
  43. Log.i(getClass().getName(),message);
  44.  
  45. }
  46. }

 Utiliser MainActivity comme auditeur

Une autre façon de gérer les événements pour les trois boutons consiste à utiliser la classe MainActivity comme objet écouteur. Nous ne voulons pas changer le fichier principal du programme tel qu’il est actuellement; De cette façon, nous pourrons y faire référence plus tard. Nous pouvons définir une autre classe qui servira de fichier de programme principal; De cette façon, il peut être côte à côte avec le programme principal original dans le même projet. Dans la barre de menus principale, cliquez sur Fichier -Nouveau Classe Java et remplissez-le comme indiqué à la figure 5-13. Vous pouvez également cliquer avec le bouton droit sur le dossier qui contient MainActivity et utiliser le menu contextuel pour ajouter une classe. 

Figure 5-12. Créer un nouveau dialogue de classe

Nous nommerons la nouvelle classe MainActivity2. Il étend la même super-classe que le programme principal d'origine. Laissez le champ "interfaces" vide et laissez l'entrée par défaut sur "Package". La visibilité publique et l'absence de modificateurs devraient convenir à notre environnement.Certains avertissements peuvent apparaître dans la fenêtre d'édition du fichier programme nouvellement créé. ils nous avertissent simplement que la nouvelle classe n'est pas enregistrée dans le fichier AndroidManifest (Figure 5-13).

Figure 5-13. MainActivity2

Laissez ceci pour le moment. nous réglerons cela plus tard. Pour le moment, notre nouveau fichier programme ne contient pas tout ce dont il a besoin pour être une classe d'activité appropriée, il ne remplace pas la méthode onCreate et ne contient aucun fichier de présentation associé. Corrigeons cela en fournissant le code manquant.

Listing 5-17. MainActivity2 Program File

 

 

 Vous devez ajouter la directive implements sur la classe. Cela signifie que leLa classe MainActivity2 doit se comporter comme s’il s’agissait d’un objet OnClickListener. C’est ce que signifie implémenter n’importe quelle interface. Nous sommes essentiellement d'accord avec un certain contrat d'objet selon lequel, quels que soient les comportements de l'interface, nous nous comportons de la même manière.La méthode onCreate contient le même code que celui du programme principal d'origine(MainActivity.java); bien sûr, nous devons toujours ajouter l'instruction setContentView et les enregistrements de vue - nous y reviendrons dans un instant. Vous remarquerez peut-être le décorateur @Nullable sur le paramètre Bundle; cela signifie simplement que l’objet Bundle, dans le cas où il est nul, n’est pas grave et qu’il peut être ignoré en toute sécuritéLa méthode onClick remplacée de l'interface OnClickListener est maintenant implémentée en tant que méthode membre de MainActivity2Il s’agit de la même implémentation de la méthode show que celle que nous avons vue dans MainActivity d’origine. 

Listing 5-19. View Registrations

 

  1. @Override
  2.  
  3. protected void onCreate(Bundle savedInstanceState) {
  4.  
  5. super.onCreate(savedInstanceState);
  6. setContentView(R.layout.activity_main);
  7.  
  8. Button b1 = (Button) findViewById(R.id.button1);
  9. Button b2 = (Button) findViewById(R.id.button2);
  10. Button b3 = (Button) findViewById(R.id.button3);
  11. ButtonListener blistener = new ButtonListener();
  12.  
  13. b1.setOnClickListener(blistener);
  14. b2.setOnClickListener(blistener);
  15. b3.setOnClickListener(blistener);
  16. }

La méthode onCreate de l'exemple de code précédent n'est pas si différente de nos codes de gestion d'événements. La seule différence est que nous utilisons le même objet pour gérer les événements des trois boutons. Aucun des boutons n'a son propre auditeur dédié, comme c'était le cas avec l'utilisation de classes anonymes. Dans cette approche, la logique du programme est routée à l'intérieur de l'objet écouteur (ButtonHandler). package com.example.ted.eventhandling1;

import android.os.Bundle;

import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Toast;

/**  * Created by ted on 06/10/2017.

 */

 

 

  1. public class MainActivity2 extends AppCompatActivity
  2. implements View.OnClickListener {
  3.  
  4. @Override
  5.  
  6. protected void onCreate(@Nullable Bundle savedInstanceState) {
  7.  
  8. super.onCreate(savedInstanceState);
  9. setContentView(R.layout.activity_main); }
  10.  
  11. @Override
  12.  
  13. public void onClick(View view) {
  14. switch (view.getId()){
  15. case R.id.button1:show("Button One");
  16.  
  17. break;
  18. case R.id.button2:show("Button Two");
  19.  
  20. break;
  21. case R.id.button3:show("Button Three");
  22.  
  23. break;
  24. default:show("This should not happen");
  25.  
  26. }
  27.  
  28. }
  29.  
  30. void show(String message) {
  31.  
  32. Toast.makeText(this, message,Toast.LENGTH_LONG).show();
  33. Log.i(getClass().getName(), message);
  34.  
  35. }
  36.  
  37. }

Listing 5-20. Complete Code for MainActivity2

 

 

  1. package com.example.ted.eventhandling1;
  2.  
  3. import android.os.Bundle;
  4. import android.support.annotation.Nullable;
  5. import android.support.v7.app.AppCompatActivity;
  6. import android.util.Log;
  7. import android.view.View;
  8. import android.widget.Toast;
  9.  
  10. public class MainActivity2 extends AppCompatActivity
  11. implements View.OnClickListener {
  12.  
  13. @Override
  14.  
  15. protected void onCreate(@Nullable Bundle savedInstanceState) {
  16.  
  17. super.onCreate(savedInstanceState);
  18. setContentView(R.layout.activity_main); }
  19.  
  20. @Override
  21.  
  22. public void onClick(View view) {
  23.  
  24. switch (view.getId()){
  25. case R.id.button1:show("Button One");
  26.  
  27. break;
  28. case R.id.button2:show("Button Two");
  29.  
  30. break;
  31. case R.id.button3:show("Button Three”);
  32.  
  33. break;
  34. default:show("This should not happen");
  35.  
  36. }
  37.  
  38. }
  39.  
  40. void show(String message) {
  41.  
  42. Toast.makeText(this, message, Toast.LENGTH_LONG).show();
  43. Log.i(getClass().getName(), message);
  44.  
  45. }
  46.  
  47. }

Pour tester notre code, nous devons apporter une légère modification au fichier AndroidManifest. Pour le moment, la classe d'activité déclarée dans le manifeste est MainActivity, notre fichier de programme principal d'origine. Lorsque le moteur d'exécution Android lance une application, il examine la déclaration d'activité dans le manifeste et exécute ce programme. Nous devons modifier cette entrée pour que le moteur d'exécution Android lance MainActivity2 au lieu de MainActivity.Ouvrez le fichier AndroidManifest.xml à partir de la fenêtre de l'outil de projet. Il devrait être dans App ➤ manifeste

AndroidManifest.xml.

Listing 5-21. Activity Entry in the Manifest File

 

 

  1. <?xml version="1.0" encoding="utf-8"?>
  2.  
  3. <manifest package="com.example.ted.eventhandling1"
  4. xmlns:android="http://schemas.android.com/apk/res/android">
  5.  
  6. <application
  7.  
  8. android:allowBackup="true"
  9. android:icon="@mipmap/ic_launcher"
  10. android:label="@string/app_name"
  11. android:roundIcon="@mipmap/ic_launcher_round"
  12. android:supportsRtl="true"
  13. android:theme="@style/AppTheme">
  14. <activity android:name=".MainActivity2"> ❶
  15. <intent-filter>
  16. <action android:name="android.intent.action.MAIN"/>
  17. <category android:name="android.intent.category.LAUNCHER"/>
  18. </intent-filter>
  19. </activity>
  20. </application>
  21.  
  22. </manifest>

 Cette entrée indique à l'exécution Android le fichier Java correspondant au programme principal ou au fichier de démarrage de l'application. Définissez la valeur de l'élément activity sur «.MainActivity2», comme indiqué dans le Listing 5-13.Maintenant, vous pouvez l'exécuter dans l'émulateur.