使用
1、在build.gradle.kts开启视图绑定,用来代替findviewById
android {
...
viewBinding{
//开启视图绑定,用来替代findViewById
enable = true
}
...
}
2、在Activity中,ActivitySplashBinding
是 View Binding 自动生成,与 activity_splash.xml
布局文件绑定,包含布局中带 id
视图引用。ActivitySplashBinding.inflate(layoutInflater)
加载布局文件并返回 binding
对象,setContentView(binding.root)
将布局的根视图设置为 Activity 的内容视图。
class SplashActivity : BaseActivity() {
private lateinit var binding:ActivitySplashBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySplashBinding.inflate(layoutInflater)
setContentView(binding.root)
// setContentView(R.layout.activity_splash)
}
3、代替findviewbyId
// private lateinit var copyrightView:TextView
override fun initDatum() {
super.initDatum()
...
binding.copyright.setText(getString(R.string.copyright,currentYear))
// val copyrightView = findViewById<TextView>(R.id.copyright)
// copyrightView.setText(getString(R.string.copyright,currentYear))
}
封装
1、创建一个BaseViewModelActivity类,使用反射机制动态获取binding,简化使用 View Binding 的 Activity 的创建过程。
open class BaseViewModelActivity<VB : ViewBinding> : BaseLogicActivity() {
lateinit var binding: VB
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
//调用inflate方法,创建viewBinding
binding = ReflectUtil.newViewBinding(layoutInflater,javaClass)
setContentView(binding.root)
}
}
2、创建反射类ReflectUtil,在该类中,通过传入的LayoutInflater对象、VB类,首先获取父类的对象(BaseViewModelActivity<ActivitySplashBinding>)。type.actualTypeArguments[0]代表ActivitySplashBinding。然后通过反射传递LayoutInflater对象并得到ActivitySplashBinding中的静态方法inflate。接下来,通过反射调用该方法并返回一个ActivitySplashBinding对象。
object ReflectUtil {
/**
* 创建view binding
*/
fun <VB> newViewBinding(layoutInflater: LayoutInflater, clazz: Class<*>): VB {
return try {
//获取泛型参数对象
val type = try {
clazz.genericSuperclass as ParameterizedType
} catch (e: ClassCastException) {
clazz.superclass.genericSuperclass as ParameterizedType
}
//type.actualTypeArguments[0]代表BaseViewModelActivity<VB>中的第一个元素ViewBinding,
//被调用是代表具体的VB
val clazzVB = type.actualTypeArguments[0] as Class<VB>
//获取inflate方法
//在vb中有public static ActivitySplashBinding inflate(LayoutInflater inflater) {
// ...
}
val inflateMethod = clazzVB.getMethod("inflate", LayoutInflater::class.java)
//getMethod的参数是:
//方法名:"inflate",表示要获取的方法是 inflate。
//方法参数类型:LayoutInflater::class.java,表示 inflate 方法的参数是
inflateMethod.invoke(null, layoutInflater) as VB
//invoke中
//第一个参数:方法所属的对象。如果是静态方法,则传入 null。
//后续参数:方法的实际参数
} catch (e: Exception) {
e.printStackTrace()
throw RuntimeException(e)
}
}
}
3、当SplashActivity调用该方法时,可省略更多冗余代码
class SplashActivity : BaseViewModelActivity<ActivitySplashBinding>() {
// private lateinit var binding:ActivitySplashBinding
// override fun onCreate(savedInstanceState: Bundle?) {
// super.onCreate(savedInstanceState)
// binding = ActivitySplashBinding.inflate(layoutInflater)
// setContentView(binding.root)
setContentView(R.layout.activity_splash)
//
// }
简化成功!