使用拓展方法+内联函数前
viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
}
override fun onPageSelected(position: Int) {
val radioButton = rg_tabs.getChildAt(position) as RadioButton
radioButton.isChecked = true
}
override fun onPageScrollStateChanged(state: Int) {
}
})
使用拓展方法+内联函数后
viewPager.addListener {
val radioButton = rg_tabs.getChildAt(it) as RadioButton
radioButton.isChecked = true
}
实现原理
看上面的简化写法,你一定会有两个疑问:
- viewPager哪来的addListener方法
- 上面的代码是怎么关联到onPageSelected方法的
第一个问题很简单,拓展函数就可以了,我们定义了一个如下的拓展函数
inline fun ViewPager.addListener(
crossinline onScrollStateChanged: (state: Int) -> Unit = {},
crossinline onScrolled: (position: Int, positionOffset: Float, positionOffsetPixels: Int) -> Unit = { position, positionOffset, positionOffsetPixels -> },
crossinline onSelected: (position: Int) -> Unit = {}
) {
val listener = object : ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {
onScrollStateChanged(state)
}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
onScrolled(position, positionOffset, positionOffsetPixels)
}
override fun onPageSelected(position: Int) {
onSelected(position)
}
}
addOnPageChangeListener(listener)
}
第二个问题,看上面的拓展函数,我们就知道,其实在调用addListener时,就是创建了一个ViewPager.OnPageChangeListener对象,然后添加到addOnPageChangeListener中,本质上我们最原始的代码没有区别
按照上面的拓展方法,其实我们应该这么写:
viewPager.addListener (onSelected = { position->
val radioButton = rg_tabs.getChildAt(position) as RadioButton
radioButton.isChecked = true
})
但是,实际上,上面的代码可以有两个简化
- 如果方法的参数的最后一个是lambda表达式,可以不写表达式的参数,将表达式的方法体放到外面去
viewPager.addListener { position->
val radioButton = rg_tabs.getChildAt(position) as RadioButton
radioButton.isChecked = true
}
- 如果lambda表达式的入参只有一个,入参可以省略,用it代替
vp.addListener {
val radioButton = rg_tabs.getChildAt(it) as RadioButton
radioButton.isChecked = true
}
好了,最终简化版完成了,enjoy吧。
其实,这个简化技巧可以用到很多地方,比如网络请求,可以将什么网络请求、线程切换、序列化等等都放在拓展方法内部,将成功的回调方法做成lambda表达式放在参数的最后一位,前面也可以加一个错误回调的lambda表达式参数,但一般情况下可以省略,用默认实现就好,这样代码就可以写成
request.addListener {
handleResponse(it)
}