Kotlin uses higher order functions to implement callback mode

  • 2021-11-30 01:19:16
  • OfStack

lambda and higher order functions

I learned lambda and higher-order functions before, and then listening for onClick events in android development is a very common function. The general implementation of kotlin is as follows:


  rootView.setOnClickListener { view ->
    println(" Clicked on this ID=${view.id} Adj. view")
  }

Then, in the development, it is inevitable that we should also write some code such as custom listening. At this time, if we still use the idea of java to realize it, it will be a bit far away.

Implementation of java Idea

Our general approach in java is as follows

Define 1 interface
Define 1 interface type variable
Define 1 set method
Call the set method to set the implementation class of the interface

The implementation with kotlin is as follows


class MyView{
  // Definition 1 Interface 
  interface IOnLabelCheckedListener {
    fun onLabelCheck(label: String)
  }
  // Definition 1 Interface type variables 
  private var onLabelChecked: IOnLabelCheckedListener? = null

  private fun initView(context: Context) {
    view.setOnCheckedChangeListener { radioGroup, i ->
        onLabelChecked.onLabelCheck(radioGroup.findViewById<RadioButton>(i).text.toString())
    }
  }
  // Definition 1 A  set  Method 
  fun setOnLabelCheckedListener(e: IOnLabelCheckedListener) {
    this.onLabelChecked = e
  }
}

   //  Call set Method, implemented through anonymous inner classes 
    MyView.setOnLabelCheckedListener(object : LabelBarView.IOnLabelCheckedListener {
      override fun onLabelCheck(label: String) {

      }
    })

The problem of this implementation

Of course, it is too complicated. Moreover, when I first wrote 1 like this, I couldn't understand why MyView. setOnLabelCheckedListener expression couldn't be passed in inside MyView method. lambda expression existed to replace anonymous inner class. And if this interface defines an interface of type java, you can use the lambda expression. Why is this? Finally, we guess that kotlin and java are wrapped with another layer in the middle when they call each other, and we directly use kotlin to define that there is no intermediate layer in this interface, and the set method we define is not a high-order function, so of course we cannot use lambda expression.

Let's use the idea of kotlin to implement callback

Use higher-order functions to implement

One important difference between kotlin and java is functional programming. In the idea of functional programming, the function is a first-class citizen. When using kotlin, we should make more use of this thinking to think about problems. Kotlin provides a high-order function, which can directly use a function as the return value. For me who is used to programming java, it is difficult to understand it at first. Below, I write down my idea of realizing a high-order function step by step, hoping to help everyone.

First of all, I can think of function transfer, which can be realized by replacing anonymous inner classes with lambda


// Start with the basics and put anonymous inner classes through  lambda  Realization 
MyView.setOnLabelCheckedListener(object : MyView.IOnLabelCheckedListener {
    override fun onLabelCheck(label: String) {
     println(label)
    }
})
//  First  MyView.IOnLabelCheckedListener  Only in 1 Methods  onLabelCheck(label: String)
//  So you can write  lambda  The expression is as follows 
var lam: (String) -> Unit = { label -> println(label) }

Then, the written lambda needs to be passed in. At this time, the setOnLabelCheckedListener method is required to be a high-order function


  //  Receive here 1 A   The expression we modified above  lam , Its internal implementation should be to put  e  Object assigned to the current class 1 Objects 
  fun setOnLabelCheckedListener(e: (String) -> Unit) {
    this.lisenter = e
  }
 
  // Apparently  lisenter  It should be like this 
  var linsnter: (String) -> Unit = {}

Finally, use linsnter for callback


  private fun initView(context: Context) {
    view.setOnCheckedChangeListener { radioGroup, i ->
      linsnter(radioGroup.findViewById<RadioButton>(i).text.toString())
    }
  }

Final code result:


class MyView{
  var linsnter: (String) -> Unit = {}

 private fun initView(context: Context) {
    view.setOnCheckedChangeListener { radioGroup, i ->
      linsnter(radioGroup.findViewById<RadioButton>(i).text.toString())
    }
 }

 fun setOnLabelCheckedListener(e: (String) -> Unit) { 
  this.lisenter = e
 }
}
  //  When called, set the variable  lam  Omit, use directly 1 Expressions 
  view.setOnLabelCheckedListener { label ->
    println(label)
  }

There are two major differences between the final code and the previous code, 1 is that there is no interface definition, and 2 is that there is no anonymous inner class.

Better use of higher-order functions

The use of higher-order functions can make our code simpler more often, such as the following code:


  fun refreshData(e: ((Boolean, String) -> Unit)): Boolean {

    if (!UserInfoManager.getInstance().isLogin) {
      e(false, " Not logged in ")
      return false
    }

    NETWorkUtils.request(ApiParamter(), object : ApiListener<ResponseData> {
      override fun onApiCompleted(data: ResponseData?) {
          e(true, " Success ")
      }

      override fun onApiError(errorCode: Int, errorCodeMessage: String) {
         e(false, errorCodeMessage)
      }
    })
    return true
  }

Then when it is called, it can be like this:


   mView.refreshData { isSuccess, msg ->
      //do something
  }

Is it very simple, omitting to write another interface. At the same time, if java is used to call refreshData method, it is also possible:


    mView.refreshData(new Function2<Boolean, String, Unit>() {
      @Override
      public Unit invoke(Boolean aBoolean, String s) {
        // do something
        return null;
      }
    });

Kotlin provides a series of Function interface classes for java to use when calling high-order functions, and supports up to 22 parameters. If you are interested, you can see 1.


Related articles: