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

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();
    } 
}
大家讲道理
大家讲道理

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

全部回覆(5)
迷茫

這本質上是一個方法呼叫。假設我們有兩個類別A和B,我們預期在A的某個時刻呼叫B的某個方法,我們可以讓A保持一個B的引用,在適當的時機進行方法呼叫:

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();
        // ...
    }
}

以上程式碼實現了,在A的某個時刻(發生某件事情的時候),我們通知B去做一些事情,這就是一個簡單的監聽模式。你看,這裡並不是B時時刻刻去監聽A的動作,而是在某個時刻A主動觸發了B的方法。

在這裡,把B換成Listener,就變成了我們熟悉的監聽器。

所以我們可以寫一個B的子類,也就實作了一個自訂監聽器:

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

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

在設計模式方面,有一條推薦的做法,叫做“多用組合,少用繼承”,意思是說應該多用接口而少用繼承,我們把上面的B改成接口:

interface B {
    void doSomething();
}

然後把之前繼承的實作換成介面的實作:

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

你可以看到,用法和之前是完全一樣的。

把interface B換成interface OnClickListener,是不是就清晰很多了?這在設計模式中叫做观察者模式

推薦一本書:《Head First設計模式》,其中前兩個章節介紹了策略模式策略模式观察者模式,也就是我上面提到的內容。

迷茫

不要字面上的理解監聽器,它不是主動去檢查時間是否發生的,所以不存在每時每刻這種說法。
對我們來說,Android中的Listener其實只是一種Callback,是回呼方法。是當事件發生時,由事件發起者或內部處理者呼叫的方法。
自己寫的Listener類別並不是因為繼承了誰誰誰能監聽事件,而是要想辦法告訴事件的發起者或內部處理者,事件發生時,需要呼叫這個Listener中的指定方法,這也就是通常所要做的setListener的過程。

你給的程式碼裡已經把這個邏輯演繹得非常清楚,請先仔細看看程式碼。

大家讲道理

這是一種設計模式,只是名字叫監聽器,並不是主動觸發,是被動的。理解了這種模式你自己就可以寫一些,我們通常說的回調就是這個。

阿神

Java的Listener是規定回呼函數的介面。 Listener的實作類別(一般是匿名內部類別)就是回呼函數物件本身。 Java裡面要是想傳遞一個函數物件(也稱為閉包),就需要這樣做。

黄舟

很久之前,我學java的時候,也問了同學這個問題,你採納的那個人已經說很清楚了,這本質是一個方法調用。
其實你只要上課認真聽講了,下課認真把老師打的代碼打了一遍,你就明白這個問題了,
可以肯定的是,總是喜歡把問題拖著,到後來再弄清楚,這樣是不行的。
建議多打代碼,每天不少於700行。
你覺得沒代碼打?問別人弄清楚的問題,那個程式碼一定要打3遍,沒代碼打就打些有意義的小程式。
堅持打程式碼,就是從一開始就堅持強大。

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板