一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情。
1.泛型实化
先看一个函数,用来判断参数name
是否为某种指定泛型类型并执行相对应逻辑:
fun <T> test(name: Any, block: () -> Unit) {
if (name is T) {
block()
}
}
上面的name is T
是会直接报错的,或者调用T::class.java
也是会报错的,编译器是不支持这种写法的。
为了通过编译器的支持,我们可能会做如下繁琐的封装:
fun test2(name: Any, block: () -> Unit) {
when(name) {
is String -> block()
is Int -> block()
is Double -> block()
is GCCheck -> block()
else -> block()
}
}
写起来十分麻烦,这个时候泛型实化要登场了:
泛型T加上
reified
声明并且方法也要加上inline
修饰
然后我们就可以优雅写出下面代码:
inline fun <reified T> test(name: Any, block: () -> Unit) {
if (name is T) {
block()
}
}
可以看到,test
方法写起来更加简单,请注意reified
一定要搭配inline
使用。
2.泛型实化应用案例讲解
- 利用泛型实化更加简单启动Activity 看下平常代码中是怎么启动Activity的:
startActivity(Intent(this, ZygoteActivity::class.java))
又或者我们还可能进行如下封装:
fun Intent.startActivity(activity: AppCompatActivity) {
activity.startActivity(this)
}
//使用
Intent(this, ZygoteActivity::class.java).startActivity(this)
但是上面写起来都太复杂了,其实上面封装关键都是要拿到目标Activity的Activity::class.java
类型,这恰好到了泛型实化发挥的场景了:
定义如下封装:
inline fun <reified T> Activity.startActivity() {
startActivity(Intent(this, T::class.java))
}
看下优雅的使用:
startActivity<ZygoteActivity>()
有时候我们在进行Activity跳转到还要通过Intent传参,下面我们对这个startActivity
扩展函数进一步封装:
inline fun <reified T> Activity.startActivity(block: Intent.() -> Unit = {}) {
startActivity(Intent(this, T::class.java).apply(block))
}
我们增加一个带接收者的函数类型参数block: Intent.() -> Unit
,并给与默认值,看下使用效果:
startActivity<ZygoteActivity> {
putExtra("key", "value")
putExtra("key2", 100)
}
使用起来就是这么简单丝滑。
- 搭配Gson实现快捷反序列化
这里就不再细说了,可以参考我之前写的文章:Gson序列化的TypeToken写起来太麻烦?优化它,最终的封装效果如下:
使用起来也是特别的简单丝滑: