編程史上有兩個令人匪夷所思的說辭,一個是訂閱,一個是回調函數。
我想應該還有很多同學為“事件的訂閱”和“回調函數”所困擾,因為事情本來就不應該按這個套路來解釋。
多直白,所謂的“回調函數”你完全可以線性的理解它,現在起,你只需要知道“接口”與“實現”!
常見的場景如下:
1.我寫了個模塊,模塊中有一些功能要實現,但我暫時沒空做,或者需要他人的協助來完成具體的實現。因此我先定義一個接口,接口中根據我的需要定義一些空方法,在我的模塊中調用這些空方法,這些方法的具體實現交給未來實現該接口的類中去實現。
2.我寫的是可復用的控件,例如點擊它會完成什么功能,需要使用他的人到時候自行去填寫。因此我先定義一個接口,接口中根據我的需要定義一些空方法,在我的控件中調用這些空方法,這些方法的具體實現交給未來實現該接口的類中去實現。
3.我在設計模塊,就像羅列大綱一樣,在接口中把該有的方法大致羅列出來,然后由實現這個接口的類來實現這些方法。
4.我寫了個模塊,有些功能適合放在特定的類中去實現。因此我先定義一個接口,接口中根據我的需要定義一些空方法,在我的模塊中調用這些空方法,這些方法的具體實現交給未來實現該接口的類中去實現。
……
有沒有發現,盡管出於不同的目的,但是他們的套路都是一樣的:
1.定義接口,接口中定義空方法
2.在不方便或不適合實現方法的地方調用這些空方法
3.在實現該接口的類中具體實現這些方法
對於調用空方法的地方來說,他們調用未來會被實現的空方法,和直接調用一個現成的方法,效果是一樣的。
可能光看文字描述並無助於你的理解,那么下面的代碼,幫助你順流直下秒懂這一切。
1.我寫了一個可復用的控件,里面有個按鈕的點擊事件需要放在未來調用該控件的Activity中實現
1 public class TitleBar extends RelativeLayout { 2 3 public TitleBar(Context context, AttributeSet attrs, int defStyleAttr) { 4 super(context, attrs, defStyleAttr); 5 } 6 7 public TitleBar(Context context) { 8 super(context); 9 } 10 11 public TitleBar(Context context, AttributeSet attrs) { 12 super(context, attrs); 13 14 LayoutInflater.from(getContext()).inflate(R.layout.title_bar, this); 15 } 16 17 private Button btnBack; 18 19 private void initView() { 20 btnBack = (Button) this.findViewById(R.id.btn_back); 21 btnBack.setOnClickListener(new OnClickListener() { 22 @Override 23 public void onClick(View v) { 24 25 } 26 }); 27 } 28 }
2.因此我定義一個接口,其中定義控件點擊事件中要執行的方法的空方法,然后在控件的點擊事件中調用該空方法。
1 public class TitleBar extends RelativeLayout { 2 3 public TitleBar(Context context, AttributeSet attrs, int defStyleAttr) { 4 super(context, attrs, defStyleAttr); 5 } 6 7 public TitleBar(Context context) { 8 super(context); 9 } 10 11 public TitleBar(Context context, AttributeSet attrs) { 12 super(context, attrs); 13 14 LayoutInflater.from(getContext()).inflate(R.layout.title_bar, this); 15 initView(); 16 } 17 18 private Button btnBack; 19 20 private void initView() { 21 btnBack = (Button) this.findViewById(R.id.btn_back); 22 btnBack.setOnClickListener(new OnClickListener() { 23 @Override 24 public void onClick(View v) { 25 //5.調用該接口的該空方法 26 mTitleBarListener.btnBackClick(); 27 } 28 }); 29 } 30 31 //1.定義該接口 32 public interface TitleBarListener { 33 //2.定義該空方法 34 void btnBackClick(); 35 } 36 37 //3.在控件中定義一個該接口的成員變量 38 private TitleBarListener mTitleBarListener; 39 40 //4.為該接口成員變量定義一個set方法,用於從實現類中傳入接口的實例 41 public void setOnTitleBarListener(TitleBarListener titleBarListener) { 42 this.mTitleBarListener = titleBarListener; 43 } 44 }
3.在Activity中使用該控件,傳入該接口的實例,並實現該方法
1 public class ActivityOne extends AppCompatActivity { 2 3 @Override 4 protected void onCreate(@Nullable Bundle savedInstanceState) { 5 super.onCreate(savedInstanceState); 6 setContentView(R.layout.aty_one); 7 initView(); 8 } 9 10 private TitleBar titleBar; 11 12 private void initView() { 13 titleBar = (TitleBar) findViewById(R.id.titleBar); 14 //6.調用該接口的set方法,將接口的實例傳入並具體實現控件中調用的空方法 15 titleBar.setOnTitleBarListener(new TitleBar.TitleBarListener() { 16 @Override 17 public void btnBackClick() { 18 //此處填充我們具體要實現的內容 19 } 20 }); 21 } 22 }
怎么樣,容易理解吧。未來我們一定還會遇到各種各樣奇葩的說辭,需要你多實踐,透過表象看其本質,這樣就不能輕易的被迷惑了。