java - 自己写的 interface 为什么能作为监听器?
大家讲道理
大家讲道理 2017-04-18 09:53:29
0
5
402

Android 里面自定义监听器我没搞明白. 监听器是能够做到每时每刻监听是吗? 那像这些自己写出来的监听器究竟是怎么做到监听的?

像这个Android 帮助文档上的实现 dialog 的代码(代码如下), 自己编的一个 interface 被 MainActivity 继承为什么就能做到监听? — NoticeDialogListener为什么能够接收到点击按钮的事件呢?

以下是上述文档的代码. 当然我问的也不仅仅是这个代码了… 谢谢回答!

For example, here's a DialogFragment that defines an interface through
which it delivers the events back to the host activity:

public class NoticeDialogFragment extends DialogFragment {

    /* The activity that creates an instance of this dialog fragment must
     * implement this interface in order to receive event callbacks.
     * Each method passes the DialogFragment in case the host needs to query it. */
    public interface NoticeDialogListener {
        public void onDialogPositiveClick(DialogFragment dialog);
        public void onDialogNegativeClick(DialogFragment dialog);
    }

    // Use this instance of the interface to deliver action events
    NoticeDialogListener mListener;

    // Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        // Verify that the host activity implements the callback interface
        try {
            // Instantiate the NoticeDialogListener so we can send events to the host
            mListener = (NoticeDialogListener) activity;
        } catch (ClassCastException e) {
            // The activity doesn't implement the interface, throw exception
            throw new ClassCastException(activity.toString()
                    + " must implement NoticeDialogListener");
        }
    }
    ... 
}

The activity hosting the dialog creates an instance of the dialog with
the dialog fragment's constructor and receives the dialog's events
through an implementation of the NoticeDialogListener interface:

public class MainActivity extends FragmentActivity
                          implements NoticeDialogFragment.NoticeDialogListener{
    ...

    public void showNoticeDialog() {
        // Create an instance of the dialog fragment and show it
        DialogFragment dialog = new NoticeDialogFragment();
        dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
    }

    // The dialog fragment receives a reference to this Activity through the
    // Fragment.onAttach() callback, which it uses to call the following methods
    // defined by the NoticeDialogFragment.NoticeDialogListener interface
    @Override
    public void onDialogPositiveClick(DialogFragment dialog) {
        // User touched the dialog's positive button
        ...
    }

    @Override
    public void onDialogNegativeClick(DialogFragment dialog) {
        // User touched the dialog's negative button
        ...
    }
}

Because the host activity implements the NoticeDialogListener—which is enforced by the onAttach() callback
method shown above—the dialog fragment can use the interface callback
methods to deliver click events to the activity:

public class NoticeDialogFragment extends DialogFragment {
    ...

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Build the dialog and set up the button click handlers
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage(R.string.dialog_fire_missiles)
               .setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // Send the positive button event back to the host activity
                       mListener.onDialogPositiveClick(NoticeDialogFragment.this);
                   }
               })
               .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // Send the negative button event back to the host activity
                       mListener.onDialogNegativeClick(NoticeDialogFragment.this);
                   }
               });
        return builder.create();
    } 
}
大家讲道理
大家讲道理

光阴似箭催人老,日月如移越少年。

répondre à tous(5)
迷茫

Il s'agit essentiellement d'un appel de méthode. Supposons que nous ayons deux classes A et B, et que nous espérons appeler une méthode de B à un certain moment dans A. Nous pouvons laisser A conserver une référence à B et effectuer des appels de méthode au moment approprié :

class B {
    void doSomething() {}
}

class A {
    private B b;
    
    public void setB(B b) {
        // 保持一个B的引用
        this.b = b;
    }
    
    public void testMethod() {
        // ...
        // 在A的某个时刻调用B的某个方法
        b.doSomething();
        // ...
    }
}

Le code ci-dessus est implémenté. À un certain moment dans A (quand quelque chose se produit), nous informons B de faire quelque chose. Vous voyez, ici B ne surveille pas les actions de A tout le temps, mais A déclenche activement la méthode de B à un certain moment.

Ici, remplacez B par Listener et il devient l'auditeur familier.

Nous pouvons donc écrire une sous-classe de B et implémenter un écouteur personnalisé :

class SubB extends B {
    @override
    void doSomething() {}
}

void main() {
    A a = new A();
    // 给A设置我们自定义的监听器
    a.setB(new SubB());
    a.testMethod();
}

En termes de modèles de conception, il existe une approche recommandée appelée « utiliser plus de combinaison et moins d'héritage », ce qui signifie que vous devez utiliser plus d'interfaces et moins d'héritage. Changeons le B ci-dessus en interface :

interface B {
    void doSomething();
}

Remplacez ensuite l'implémentation héritée précédemment par l'implémentation de l'interface :

class SubB implements B {
    void doSomething() {}
}
void main() {
    A a = new A();
    // 给A设置我们自定义的监听器
    a.setB(new SubB());
    a.testMethod();
}

Comme vous pouvez le constater, l'utilisation est exactement la même qu'avant.

Remplacer l'interface B par l'interface OnClickListener. Sera-t-elle beaucoup plus claire ? C'est ce qu'on appelle 观察者模式 dans les modèles de conception.

Recommander un livre : "Head First Design Pattern", les deux premiers chapitres présentent 策略模式 et 观察者模式, c'est ce que j'ai mentionné ci-dessus.

迷茫

Ne comprenez pas littéralement l'auditeur. Il ne vérifie pas activement si l'heure se produit, donc chaque instant n'existe pas.
Pour nous, Listener sous Android n'est en fait qu'un rappel, une méthode de rappel. Il s'agit d'une méthode appelée par l'initiateur de l'événement ou le gestionnaire interne lorsqu'un événement se produit.
La classe Listener écrite par moi-même n'est pas seulement parce qu'elle hérite de tel ou tel, elle peut écouter l'événement, mais pour trouver un moyen d'indiquer à l'initiateur ou au gestionnaire interne de l'événement que lorsque l'événement se produit, le spécifié La méthode dans ce Listener doit être appelée. C'est également le processus de setListener qui est habituellement effectué.

Cette logique a été déduite très clairement dans le code que vous avez donné. Veuillez d'abord regarder attentivement le code.

大家讲道理

Il s'agit d'un modèle de conception, mais le nom est auditeur. Il n'est pas déclenché activement, mais passif. Une fois que vous avez compris ce modèle, vous pouvez en écrire vous-même. C'est ce que nous appelons habituellement les rappels.

阿神

Java's Listener est une interface qui spécifie les fonctions de rappel. La classe d'implémentation de Listener (généralement une classe interne anonyme) est l'objet fonction de rappel lui-même. Si vous souhaitez transmettre un objet fonction (également appelé fermeture) en Java, vous devez le faire.

黄舟

Il y a longtemps, alors que j'apprenais Java, j'ai aussi posé cette question à mes camarades de classe. La personne que vous avez adoptée a déjà dit très clairement qu'il s'agissait essentiellement d'un appel de méthode.
En fait, tant que vous écoutez attentivement en classe et tapez soigneusement le code écrit par le professeur après le cours, vous comprendrez le problème
Ce qui est sûr, c'est que j'aime toujours remettre à plus tard le problème et le comprendre. sortir plus tard, ce n'est pas possible.
Il est recommandé d'écrire plus de codes, pas moins de 700 lignes par jour.
Vous pensez qu'il n'y a pas de code à saisir ? Lorsque vous posez des questions que d'autres ont comprises, vous devez taper le code trois fois. Si vous ne tapez pas le code, tapez quelques petits programmes significatifs.
S'en tenir au codage signifie rester fort dès le début.

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal