web-dev-qa-db-fra.com

Android - OnClick Listener dans une classe distincte

Est-il possible de créer une classe secondaire pour contenir l'écouteur OnClick? Vous ne créez pas de classe d'activité?

Je trouve juste que mettre des écouteurs OnClick dans la classe d'activité principale est juste désordonné et je préfère les avoir dans des classes séparées. Merci

28
Pztar

Bien sûr, c'est possible. Créez simplement une classe qui implémente View.OnClickListener Et définissez-la comme écouteur sur View. Par exemple:

public class ExternalOnClickListener implements View.OnClickListener {

    public ExternalOnClickListener(...) {
        // keep references for your onClick logic 
    }

    @Override public void onClick(View v) {
        // TODO: add code here
    }

}

Et puis définissez une instance de la classe ci-dessus comme écouteur:

view.setOnClickListener(new ExternalOnClickListener(...));

Le constructeur paramétré est facultatif, mais il est très probable que vous ayez besoin de passer quelque chose pour que votre logique onClick(...) fonctionne.

L'implémentation anonyme d'une classe est généralement plus facile à utiliser. Juste une pensée.

30
MH.

Au lieu de mettre onCLicklistener dans une classe distincte, pourquoi n'essayez-vous pas de définir onClickListener en dehors de onCreate() ??

Par exemple: comme ceci

onCreate ()

yourViewName.setOnClicklistener(listener):

En dehors de onCreate ()

private OnClickListener listener    =   new OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub

        }
    };
10
Renjith

Oui, vous pouvez. Cependant, faire de l'auditeur une classe interne présente un avantage: il peut accéder directement aux champs et aux variables de votre classe d'activité. Si vous en faites une classe distincte et que votre écouteur doit réellement accéder à 5 vues, votre constructeur d'écouteur pourrait ressembler à ceci:

MyListener listener = new MyListener(context, button, textView1, textView2, ratingBar, imageView);

Ce qui est aussi un peu encombrant. Si votre auditeur est simple, allez-y et faites-en une classe distincte. Sinon, c'est à vous de la lisibilité.

5
Lawrence Choy

Permettez-moi de partager comment je le code en utilisant MVP. C'est la meilleure façon de créer un code propre. N'oubliez pas que chaque classe doit avoir une interface pour la contrôler. Je vais vous montrer le plus simple.

Supposons que vous souhaitiez griller un texte surClick et le contrôler à partir d'une autre classe. Voici comment ça fonctionne. La création d'interfaces ne sert qu'à se connecter et vous pouvez facilement consulter le code.

  1. Créez une interface pour cette classe MainActivity.

    public interface MainActivityView {
        void showToast();
    }
    
  2. Créez une autre interface pour la classe Presenter.

    public interface IMainPresenter<V extends MainActivityView> {
        /*Generic Type is to make sure it comes from MainActivity class only and to avoid other class to access it.*/
        void onAttach(V mainView);
        void onButtonClick();
    }
    

N'oubliez pas que les interfaces ne sont rien d'autre que de remplacer la méthode pour chaque classe.

  1. Créer une classe Presenter

    public class MainPresenter<V extends MainActivityView> implements IMainPresenter<V> {
    
        private V mainActivityView;
    
        @Override
        public void onAttach(V mainActivityView) {
            this.mainActivityView=mainActivityView;
        }
    
        public V getView() {
            return mainActivityView;
        }
    
        @Override
        public void onButtonClick() {
            getView().onToast(); //This is the method from MainActivity controlling with this class
        }
    }
    
  2. Je vais ignorer la disposition activity_main.xml car il n'y a qu'un bouton avec id = "@ + id/buttonId". Dans MainActivityClass,

    public class MainActivity extends AppCompactActivity implements MainActivityView {
    
    Button btn;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            MainPresenter mainPresenter = new MainPresenter();
            mainPresenter.onAttach(this);
    
            btn = findViewById(R.id.buttonId);
    
            btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    mainPresenter.onButtonClick(); //Here, check No.3 again!
                }
             });
        }
    
        @Override
        public void showToast() {
             Toast.makeText(this, "Hello", Toast.LENGTH_SHORT).show();
        }
    }
    
  3. Tout ce que je veux vous dire, c'est que. Si vous créez des objets dans une classe, elle ne peut pas effectuer de test unitaire. C'est pourquoi vous ne voyez aucun nouvel objet appeler dans Android. Ainsi, vous pouvez utiliser le modèle singleton (Voici le type paresseux) dans la classe Presenter. Je vais supprimer son interface et Generic pour le voir clairement.

    public class MainPresenter {
    
           private static final MainPresenter mainPresenter = new MainPresenter();
    
           MainPresenter() {}
    
           public static MainPresenter getInstance() {
                   return mainPresenter;
           }
    
           //Some methods here can be get it once you create object with getInstance();
    }
    

Et vous pouvez donc obtenir ses méthodes de MainActivity comme ceci. Au lieu de créer des objets comme celui-ci ...

    MainPresenter mainPresenter = new MainPresenter();

Vous pouvez l'obtenir comme ça ...

    MainPresenter mainPresenter = mainPresenter.getInstance();

Plus d'exemples pour le modèle singleton peuvent être trouvés ici, https://www.journaldev.com/1377/Java-singleton-design-pattern-best-practices-examples

  1. Enfin, l'utilisation de l'électricité statique n'est pas un très bon choix car elle utilise de l'espace mémoire, que vous l'utilisiez ou non. Et donc, vous pouvez créer des objets dans Application Layer pour l'obtenir avec un Typecasting. Je suis sûr que vous n'avez pas besoin de tester unitairement cette couche d'application.

    public class AppLayer extends Application {
    
        private MainPresenter mainPresenter;
    
        @Override
        public void onCreate() {
            super.onCreate();
    
            mainPresenter = new MainPresenter();
        }
    
        public MainPresenter getMainPresenter() {
            return mainPresenter;  
        }
    

Et vous devez donner un nom de classe dans Application dans manifest.xml

    <application
    Android:name=".AppLayer"
    Android:allowBackup="true"
    Android:icon="@mipmap/ic_launcher"
    Android:label="@string/app_name"
    Android:roundIcon="@mipmap/ic_launcher_round"
    Android:supportsRtl="true"
    Android:theme="@style/AppTheme">

    </application>

Et vous pouvez l'obtenir avec un Typecast dans MainActivity comme celui-ci!

    MainPresenter mainPresenter = ((AppLayer)getApplication()).getMainPresenter();
  1. Pour d'autres études, je vous suggère d'apprendre ButterKnife, Dagger 2 et SOLID Principles. Il vous aidera à créer un codage propre. Amusez-vous!
1
Dracula Oppa

Tu peux le faire. Mais pensez simplement que vous n'aurez pas de référence à l'activité, ni à ses attributs, y compris toutes les vues. (sauf si vous les rendez publics ou accessibles avec les méthodes getters).

Aussi, soyez extrêmement prudent avec le stockage des références à l'activité ou à tout membre de l'auditeur, car ils pourraient éviter que le garbage collector récupère la mémoire de l'auditeur.

1
Robert Estivill
public class CommonClick {
    public static  void commonClick(final AppCompatActivity context){
        context.findViewById(R.id.appbar).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });
    }
}
0
nithin joseph