接口回调,用最简单的一个匿名内部类来讲解(附接口回调高级应用场景,让你对接口的了解登堂入室)
接口回调,是Java开发者必须要学的一个东西,可是他呢,书上没有,大神博客里也没有,所以导致了有部分小伙纸并不了解这个知识,所以这里做一个最简单的讲解。
(先不牵扯什么异步回调、同步回调)
首先,只需要记住一点,接口回调的含义就是把代码换个地方写。
正常我们是这样写的
public class Data3 extends MyData { Data3() { System.out.print("-----"); }
可是我们因为某种原因,不得不把代码放到另外一个地方去写,怎么办?我们第一时间想到的是,再新建一个方法,调用这个方法即可。
public class Data3 extends MyData { Data3() { cal(); } void cal() { System.out.print("-----"); }这样其实已经算是回调了,但是我们没有采用接口,采用的是方法,所以称之为方法回调。
但是因为种种原因(原因稍后会讲),我们不能总写在我们这一个类里吧?所以我们需要弄一个类,这里用内部类的形式
public class Data3 extends MyData { Data3() { C c = new C(); c.cal(); } class C { void cal() { System.out.print("-----"); } }
但是总是要新建一个类,这性能开销和代码量开销也太大了吧!所以我们采用接口的形式
public class Data3 extends MyData { Data3() { call.whatToDo(); } Call call = new Call() { @Override public void whatToDo() { System.out.print("-----"); } }; interface Call { void whatToDo(); } }
定义一个内部接口,再“实例化”这个接口,再调用这个接口里的方法。这就是接口回调了。
有人可能有疑问,为什么接口可以实例化呢?其实上述代码,是创建了一个匿名内部类,再继承了这个接口,效果等同于下面的代码:
public class Data3 extends MyData { Data3() { xxx x = new xxx(); x.whatToDo(); } interface Call { void whatToDo(); } class xxx implements Call { @Override public void whatToDo() { System.out.print("-----"); } } }创建一个类,继承这个接口,调用的是这个类的方法。而上面的就是通过匿名内部类的形式,其实就是Java的语法糖,让你可以少些许多代码。讲到这里,看官肯定已经对接口回调掌握通透了。
下面来分析下,为什么需要用接口回调,接口回调的应用场景是怎么样的。
onClick就是一例
mRv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //do some thing } });当你的点击事件点击了,他不会立刻执行代码,他会执行onClick方法,而onClick方法是交给我们来实现的。所以我们可以验证我们的结论,接口回调就是让你的代码换一个地方执行。如果你没有设置这个监听器的话,那么虽然有点击事件,但是方法肯定得不到执行。但是如果设置了监听器的话,你所设置的接口里的方法就会得到执行。所以我们想进行接口回调,就必须让调用者得到你这个接口。很显然这个setOnClickListener就是一个传递接口的方法。
可以看一下源码
public void setOnClickListener(@Nullable OnClickListener l) { if (!isClickable()) { setClickable(true); } getListenerInfo().mOnClickListener = l; }看,这里就是把我们传进来的接口赋值了。可想而知,最后我们执行的时候,肯定会调用getListenerInfo().mOnClickListener.onClick,感兴趣的同学可以自行查看源码。我们说了我们想进行接口回调,就必须让调用者得到你这个接口,我们之前为什么没有设置接口的方法呢?因为接口就是一个成员变量啊,自然可以直接调用。而如果你平时在用的时候,发现想要让两个类之间进行通信,那么你必须先获取其中的那个类的实例,比如说是object,再调用objet.setListener(listener)即可。
其实这种简单的应用还有很多很多,下面介绍一下进阶的应用。Android消息机制。
安卓的消息机制和接口回调有啥区别呢?其实消息机制的基础就是接口回调!只不过,他把你所有的接口都进入一个队列,可以灵活自如地控制这一系列的回调何时执行,先后顺序。上图:
图中的每个小方块,都是一个接口。这里就是消息的灵活性了。此外他可以灵活地切换线程,实现线程间的通信,这也是普通的接口回调做不到的。
看似神秘的观察者模式
何为观察者模式,他和接口回调的区别简单来说就是他是一对多的。比如有多个观察者同时观察着一个被观察者,在被观察者改变的时候,观察者全部都观察到了,并且做出了响应。这个过程看似高大上,其实无非也不过是利用了接口回调。 已经精通接口回调的你应该可以轻松想到是怎么实现的了。他就是当被观察者内容改变时,会执行被观察 者中的某个方法,而该方法里面调用的是所有观察者接口中的方法,从而实现了一对多的观察。
再上升一下,架构,MVP模式
MVP分V层,P层,M层。通俗来讲,V是UI,P是媒婆,M是业务。P中会维护V层和M层的引用,通过分别调用V层和M层的接口中的方法,来实现业务和UI的分离。