Java|今天起,别再扯订阅和回调函数

 

编程史上有两个令人匪夷所思的说辞,一个是订阅,一个是回调函数。

 

我想应该还有很多同学为“事件的订阅”和“回调函数”所困扰,因为事情本来就不应该按这个套路来解释。

 

 

多直白,所谓的“回调函数”你完全可以线性的理解它,现在起,你只需要知道“接口”与“实现”!

常见的场景如下:


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 }

 

怎么样,容易理解吧。未来我们一定还会遇到各种各样奇葩的说辞,需要你多实践,透过表象看其本质,这样就不能轻易的被迷惑了。

posted @ 2016-07-18 22:28  Myatejx  阅读(1371)  评论(3编辑  收藏  举报