參考博客如下
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類
回調的理解
回調其實是一種雙向調用模式,也就說調用方在接口被調用時也會調用對方的接口
翻譯翻譯就是“實現了抽象類/接口 的實例實現了父類的提供的抽象方法后,將該方法交還給父類來處理”