Android回調機制淺談

參考博客如下
http://blog.csdn.net/xiaanming/article/details/8703708
http://www.lxweimin.com/p/3f86b7949f20
http://blog.csdn.net/xsf50717/article/details/50520462
這是看了這三篇關于回調的博客后所做的總結,新手小白,不好的地方見諒見諒!

經典回調方式

  • class A實現接口CallBack callback——背景1
  • class A中包含一個class B的引用b ——背景2
  • class B有一個參數為callback的方法f(CallBack callback) ——背景3
  • A的對象a調用B的方法 f(CallBack callback) ——A類調用B類的某個方法 C
  • 然后b就可以在f(CallBack callback)方法中調用A的方法 ——B類調用A類的某個方法D

下面舉一個小例子

/*定義一個接口Callback*/
interface Callback{
    void doCallback(String result);
}
/*A類實現接口*/
class A implements Callback{
/*A類持有B類的引用,并把b傳入A*/
    B b;
    A(B b){
        this.b = b;
    }
    /*定義A類方法*/
    public void funtionA(){
        //此時b方法傳入的參數必須是Callback的子類,這里我們傳入A,因為A實現了Callback
        b.setOnClickListener(A.this);
    }
    
    @Override
    public void doCallback(String result) {
        System.out.println("the answer is:"+result);
        
    }

}

class B {
    //創建一個含有Callback實例的B類方法
    public void setOnClickListener(Callback callback){
        String answer = "callback";
        /*B類方法中調用A類方法,這個A類方法要包括接口中的那個抽象方法,即doCallback(),并將所得結果作為參數傳回A類中
         * 這里就是回調,實現內容在B類的回調中完成
         */
         callback.doCallback(answer);
    }
}

public class CallBackTest{
    public static void main(String [] args){
        B b = new B();
        A a = new A(b);
        //調用A類方法進回調
        a.funtionA();
    }
}

流程分析:
  • 主函數執行到a.funtionA();
  • 調用b.setOnClickListener(a);
  • String answer = "callback";表示在b中完成了該流程得到結果
  • a.doCallback(answer);然后將結果以參數的形式傳入a中,執行doCallback()方法,回調
  • System.out.println("the answer is:"+result);//a.doCallback(answer);執行后進行結果輸出
button中onclick()的第一種寫法
//這個是View的一個回調接口  
/** 
 * Interface definition for a callback to be invoked when a view is clicked. 
 */  
public interface OnClickListener {  
    /** 
     * Called when a view has been clicked. 
     * 
     * @param v The view that was clicked. 
     */  
    void onClick(View v);  
}  
package com.example.demoactivity;  
  
import android.app.Activity;  
import android.os.Bundle;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.widget.Button;  
import android.widget.Toast;  
  
/** 
 * 這個就相當于Class A 
 * @author xiaanming 
 * 實現了 OnClickListener接口---->背景一 
 */  
public class MainActivity extends Activity implements OnClickListener{  
    /** 
     * Class A 包含Class B的引用----->背景二 
     */  
    private Button button;  
  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        button = (Button)findViewById(R.id.button1);  
          
        /** 
         * Class A 調用View的方法,而Button extends View----->A類調用B類的某個方法 C 
         */  
        button.setOnClickListener(this);  
    }  
  
    /** 
     * 用戶點擊Button時調用的回調函數,你可以做你要做的事 
     * 這里我做的是用Toast提示OnClick 
     */  
    @Override  
    public void onClick(View v) {  
        Toast.makeText(getApplication(), "OnClick", Toast.LENGTH_LONG).show();  
    }  
  
}  
/** 
 * 這個View就相當于B類 
 * @author xiaanming 
 * 
 */  
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {  
    /** 
     * Listener used to dispatch click events. 
     * This field should be made private, so it is hidden from the SDK. 
     * {@hide} 
     */  
    protected OnClickListener mOnClickListener;  
      
    /** 
     * setOnClickListener()的參數是OnClickListener接口------>背景三 
     * Register a callback to be invoked when this view is clicked. If this view is not 
     * clickable, it becomes clickable. 
     * 
     * @param l The callback that will run 
     * 
     * @see #setClickable(boolean) 
     */  
      
    public void setOnClickListener(OnClickListener l) {  
        if (!isClickable()) {  
            setClickable(true);  
        }  
        mOnClickListener = l;  
    }  
      
      
    /** 
     * Click的觸發是在系統捕捉到ACTION_UP后發生并由performClick()執行的,
     *performClick里會調用先前注冊的監聽器的onClick()方法:      
     */  
    public boolean performClick() {  
        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);  
  
        if (mOnClickListener != null) {  
            playSoundEffect(SoundEffectConstants.CLICK);  
              
            //這個不就是相當于B類調用A類的某個方法D,這個D就是所謂的回調方法咯  
            mOnClickListener.onClick(this);  
            return true;  
        }  
  
        return false;  
    }  
}  

注:setOnClickListener()方法只是給mOnClickListener賦值,當用戶執行點擊操作的時候,由于事件分發機制,最終會觸發performClick()方法進而觸發onClick()方法產生回調。注意一下思維:btn.setOnClickListener();并不是執行回調,而是給回調創造條件(performClick()方法中的if語句)。

流程分析:

MainActiviy.class執行onCreate(),執行到button.setOnClickListener(this); 假設此時mc為this所指代對象,即為MainActiviy.class的一個對象,將自己傳入。
觸發點擊事件后系統執行View中的performClick(),該方法調用了mc.onClick(view v),此時把執行后結果返回給MainActivity.class,即由A類進行回調

button中onclick()的第二種寫法:匿名類寫法
//此時button為B(子)類,重寫A(父)類View中的setOnClickListener()
button.setOnClickListener(new View.OnClickListener() {
@Override 
//注意:此時傳入的參數是父類v,也就是說,會將執行結果返回給view
public void onClick(View v) { //做一些操作 doWork(); } 
});

//類似于B類中此方法

 public void setOnClickListener(Callback callback){
        String answer = "callback";
        /*B類方法中調用A類方法,這個A類方法要包括接口中的那個抽象方法,即doCallback(),并將所得結果作為參數傳回A類中
         * 這里就是回調,實現內容在B類的回調中完成
         */
         callback.doCallback(answer);

View中代碼:

//這里將OnClickListener賦值給了mOnClickListene
public void setOnClickListener(@Nullable OnClickListener l) 
{ if (!isClickable()) { 
setClickable(true); } 
getListenerInfo().mOnClickListener = l; }

public boolean performClick() { sendAccessibilityEvent(
AccessibilityEvent.TYPE_VIEW_CLICKED); 
ListenerInfo li = mListenerInfo; 
if (li != null && li.mOnClickListener != null) { playSoundEffect(
SoundEffectConstants.CLICK); li.mOnClickListener.onClick(this);
return true; } 
return false; }

觸發點擊事件后系統自動執行view中的perfromClick()方法,自然也就執行到了.mOnClickListener.onClick(view)######還是由View中onClick()調用

兩種寫法的差別在于:

第一種寫法:A類為MainActivity.class,B類為View(Button繼承View)
第二種寫法:A類為View類,B類為Button類

回調的理解

回調其實是一種雙向調用模式,也就說調用方在接口被調用時也會調用對方的接口
翻譯翻譯就是“實現了抽象類/接口 的實例實現了父類的提供的抽象方法后,將該方法交還給父類來處理”

實現方法交還給提供接口的父類處理!

不好的地方求指教!!!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容