Kotlin 高级函数实现回调详解

一、前言

在开发中,我们经常使用回调函数,命名往往是各种Callback和Listener。例如最常见的View.OnClickListener

mBtn.setOnClickListener(new View.OnClickListener() {
          
   
            @Override
            public void onClick(View v) {
          
   
                Log.d("MM","Click");
            }
        });

如果用kotlin 来写的话如下

mBtn.setOnClickListener(object :View.OnClickListener{
          
   
            override fun onClick(v: View?) {
          
   
                Log.d("MM","Click");
            }
        })

二、自定义回调函数

在 java 中我们一般的做法是这样的

  1. 定义一个接口
  2. 定义一个接口类型变量
  3. 定义一个 set 方法
  4. 调用 set 方法设置接口的实现类

用 kotlin 实现就是如下

class MyView{
          
   
    //定义一个接口
    interface IOnListener {
          
   
        fun onCheck(str: String)
    }
    //定义一个接口类型变量
    private var mListener: IOnListener? = null

    //定义一个 set 方法
    fun setListener(onListener: IOnListener) {
          
   
        this.mListener = onListener
    }

	//完成工作后调用接口方法
	fun work(){
          
   
		mListener.onCheck("完成")
	}
	
	...
}

设置接口的实现类

// 调用set方法,通过匿名内部类实现
        myView.setListener(object : LabelBarView.IOnLabelCheckedListener {
          
   
            override fun onLabelCheck(str: String) {
          
   
				println(str)
            }
        })

这样实现太复杂了,刚开始写的时候,觉得都没有java 的lambda表达式简洁,总觉得哪里不对。后来发现kotlin实现思想和java的不同。

三、使用高阶函数来实现

1.单方法回调

不需要定义接口,只定义一个函数变量

class MyView{
          
   

	lateinit var mListener: (String) -> Unit

	fun setListener(listener: (String) -> Unit) {
          
   
        this.mListener = listener
	}
    
    fun work(){
          
   
		mListener.onCheck("完成")
	}
	...
}

设置接口的实现类

myView.setListener{
          
    str ->
    	println(str)
	}

如果只有一个参数还可以这样

//it代表入参 String类 
	myView.setListeren{
          
    println(it) }

如果是用 java 来调用 setListener 方法也一样可以的:

mView.setListener(new Function2<String, Unit>() {
          
   
      @Override
      public Unit invoke(String s) {
          
   
        println(s)
        return null;
      }
    });
经验分享 程序员 微信小程序 职场和发展