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.