美文网首页
使用拓展方法+内联函数,干掉模板代码

使用拓展方法+内联函数,干掉模板代码

作者: 小鱼爱记录 | 来源:发表于2019-02-23 16:02 被阅读31次

    使用拓展方法+内联函数前

    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
    }
    

    实现原理

    看上面的简化写法,你一定会有两个疑问:

    1. viewPager哪来的addListener方法
    2. 上面的代码是怎么关联到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
    })
    

    但是,实际上,上面的代码可以有两个简化

    1. 如果方法的参数的最后一个是lambda表达式,可以不写表达式的参数,将表达式的方法体放到外面去
    viewPager.addListener { position->
        val radioButton = rg_tabs.getChildAt(position) as RadioButton
        radioButton.isChecked = true
    }
    
    1. 如果lambda表达式的入参只有一个,入参可以省略,用it代替
    vp.addListener {
        val radioButton = rg_tabs.getChildAt(it) as RadioButton
        radioButton.isChecked = true
    }
    

    好了,最终简化版完成了,enjoy吧。

    其实,这个简化技巧可以用到很多地方,比如网络请求,可以将什么网络请求、线程切换、序列化等等都放在拓展方法内部,将成功的回调方法做成lambda表达式放在参数的最后一位,前面也可以加一个错误回调的lambda表达式参数,但一般情况下可以省略,用默认实现就好,这样代码就可以写成

    request.addListener {
        handleResponse(it)
    }
    

    相关文章

      网友评论

          本文标题:使用拓展方法+内联函数,干掉模板代码

          本文链接:https://www.haomeiwen.com/subject/haspyqtx.html