苏格拉底曾说过:“不懂回调的程序员不是一个好厨子”。
但对很多刚入行的朋友来说,回调确实又是一个不明觉厉的东西,理解起来稍稍有一点摸不着头脑。那么今天,笔者就以最浅显通俗的文字,带大家来一探回调的前世今生,揭开其神秘的面纱
根据《Java核心技术 第八版》中对回调的定义,回调(callback)是一种常见的程序设计模式。在这种模式中,可以指出某个特定事件发生时应该采取的动作。
啥意思?举个例子,今天你上班上到一半的时候,老板突然跑过来说:“xxx,去把办公室地扫了,扫干净了给我说一下。”好了,然后你现在自愿去扫地。扫了半个小时终于整完了,这个时候你马上跑去办公室给老板报告:“x总,地都扫干净了!”OK,你跑去给领导报告的这个动作就叫做“回调”。
再举个程序之中运用回调的例子?
OK,对Android程序员来说,我想就算你不知道回调,你也一定知道View的点击事件,点击事件就完全符合标准的回调定义“指出某个特定事件发生时应该采取的动作”。那么我们一起来看看点击事件长什么样子
view.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { //do something } });复制代码
这是一个点击事件的常见写法,在onClick()方法里面实现view被点击时需要执行的逻辑即可。可是,这个onClickListener()是个啥?setOnclickListener()又是个啥?看官别急,且听我娓娓道来。
先甩代码
public class Coder{ //声明回调对象 private void SweepFloorListener listener; //定义回调接口 interface SweepFloorListener{ void onFinish(String str); } //回调对象的实例化 public void setSweepFloorListener(SweepFloorListener listener){ this.listener = listener; } private void fun(){ //执行回调方法 listener.onFinish("扫完啦!"); } } public class Boss{ private Coder coder = new Coder() private void fun(){ coder.setSweepFloorListener(new Coder.SweepFloorListener(){ @Override public void onFinish(String str){ //扫完地了 doSomething(str) } }); } }复制代码
OK,这样我们就实现了一个简单的回调。
仔细看,coder.setSweepFloorListener()是不是和我们上面的点击事件view.setOnclickListener()长得一模一样?一样就对了
现在我们来逐一分析回调的组成。
我们可以使用Lambda表达式来使代码看起来更优雅,其实质是没有变的,如点击事件
view.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { finish(); } });复制代码
可以用Lambda表达式改写
view.setOnClickListener(v -> finish());复制代码
这里的v表示onClick(View v)的参数v
coder.setSweepFloorListener(new Coder.SweepFloorListener(){ @Override public void onFinish(String str){ doSomething(str); } });复制代码
可以改写为
coder.setSweepFloorListener(str -> doSomething(str));复制代码
这里的str表示onFinish(String str)的参数
怎么样,看起来是不是优雅多了?
那还有没有更优雅的?
有
作为一个Android开发人员,怎么能不会Kotlin呢?Kotlin的高阶函数特性可以让我们更优雅的实现回调。
对Coder和Boss类进行改写
class Coder(){ private lateinit var onFinish: (String) -> Unit fun setSweepFloorListener(onFinish:(String) -> Unit){ this.onFinish = onFinish } private fun(){ //执行回调方法 onFinish("扫完啦!") } } class Boss(){ private coder = Coder() private fun(){ coder.setSweepFloorListener{ str -> doSomething(str) } } }复制代码
这就很优雅了,我们直接干掉了回调接口SweepFloorListener()。
卧槽,还可以这么干?
所谓高阶函数,就是指可以接收函数作为入参的函数,嗯......好像听起来跟Lambda表达式是一个东西。那么我们这里具体是怎么运用了高阶函数来实现的回调呢?
今天总结了回调的几种不同实现方式,希望能给到初级的朋友们一些帮助。
有不对之处还望各位同僚雅正。