概述
文章目录
- 历程
- viewBinding 支持
- Databinding 支持
- 使用 DataBindingUtil 封装简化
历程
先是 使用了 viewBinding feature,以避免view id重名时,查找跳转布局错误。
后来,继续接触 dataBinding feature,期间还是使用之前定义的ViewBinding封装类,也没什么问题。
就是觉得每次,实例化还是要重复写一堆一样的代码,有点麻烦。一直想简化一下,刚好最近接触到了,记录一下
viewBinding 支持
开启 viewBinding
的支持
buildFeatures {
viewBinding true
}
每个xml布局生成的 Binding类,都是实现了 ViewBinding 接口
为了简化实例化 ViewBinding
实例,有了如下封装
/**
* desc : ViewBinding、ViewDataBinding 的生成类的实例化 封装
* author : stone
* email : aa86799@163.com
* time : 2022/5/14 22:44
*/
/**
* AppCompatActivity#onCreate()使用
*/
inline fun <reified VB : ViewBinding> AppCompatActivity.inflate(): VB {
return inflateBinding<VB>(layoutInflater).apply {
setContentView(this.root)
}
}
/**
* Dialog#onCreate() 使用
*/
inline fun <reified VB : ViewBinding> Dialog.inflate(): VB {
return inflateBinding<VB>(layoutInflater).apply {
setContentView(this.root)
}
}
/**
* 继承自 ViewGroup 使用。
* 例外情况:使用<merge>布局, 生成的ViewBinding 不会生成三个参数的 inflate方法, 所以调用本方法会报错。
* 那就不能调用本封装方法,只能调用生成目标类的,如: XxxBinding.inflate(LayoutInflater.from(context), this)
*/
inline fun <reified VB : ViewBinding> ViewGroup.inflate(viewGroup: ViewGroup, attachToRoot: Boolean): VB {
return inflateBinding(LayoutInflater.from(context), viewGroup, attachToRoot)
}
/**
* Recycler.Adapter#onCreateViewHolder() 使用
* 自定义ViewGroup中使用
* ...
* 以前需要 传递 parent:ViewGroup 对象来进行初始化的布局,都可以调用本方法
*/
inline fun <reified VB : ViewBinding> inflate(parent: ViewGroup): VB {
return inflateBinding(LayoutInflater.from(parent.context), parent, false)
}
/**
* 这是一个基础方法。所有创建ViewBinding对象的地方都可以直接调用。
* 反射调用 ViewBinding.inflate(layoutInflater, viewGroup, attachToRoot) 。
* 对于 Fragment、DialogFragment 都直接使用本方法。
* 调用时,viewGroup可以不传,默认为null。
*/
@Suppress("UNCHECKED_CAST")
inline fun <reified VB : ViewBinding> inflateBinding(layoutInflater: LayoutInflater, viewGroup: ViewGroup? = null, attachToRoot: Boolean = false): VB {
return VB::class.java.getMethod("inflate", LayoutInflater::class.java, ViewGroup::class.java, Boolean::class.java)
.invoke(null, layoutInflater, viewGroup, attachToRoot) as VB
}
如上,泛型使用时,使用 reified 关键字,所以最终无法在 BaseActivity、BaseFragment 类定义中直接使用。如下,
class BaseExtendFragment<VB: ViewBinding> : Fragment() {
protected lateinit var mBinding: VB
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
mBinding = inflate(inflater, container) // 这里会报错,要求指定一个具体的ViewBinding类型
return mBinding.root
}
}
所以改成了,子类来实例化
class BaseExtendFragment<VB: ViewBinding> : Fragment() {
protected lateinit var mBinding: VB
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
mBinding = (getViewBind(inflater, container, savedInstanceState) as ViewDataBinding)
return mBinding.root
}
abstract fun <VB : ViewBinding> getViewBind(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): VB
}
而子类实现,每次都要这么重复写一次:
override fun <VB : ViewDataBinding> getViewBind(inflater: LayoutInflater, container:ViewGroup?, savedInstanceState: Bundle?): VB {
mBinding = inflateBinding(inflater, container)
return mBinding as VB
}
Databinding 支持
开启 dataBinding
的支持
buildFeatures {
dataBinding true
}
ViewDataBinding
其实这个类, 实现 ViewBinding 接口,本身是一个抽象类。
所以,只是前面的封装类中的 泛型类型改成<reified VB : ViewDataBinding>
,BaseActivity、BaseFragment 使用的地方相应的声明类型也是ViewDataBinding
当然,子类实现时,还是有一段重复代码
使用 DataBindingUtil 封装简化
abstract class BaseBindActivity<VB : ViewDataBinding>(@LayoutRes resId: Int): BaseActivity() {
protected val mBind: VB by lazy { DataBindingUtil.setContentView(this, resId) }
}
abstract class BaseBindFragment<VB : ViewDataBinding>(@LayoutRes private val resId: Int) : BaseFragment() {
protected lateinit var mBind: VB
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
mBind = DataBindingUtil.inflate(inflater, resId, container, false)
return mBind.root
}
}
直接使用 DataBinding 的gradle支持库中的工具类 DataBindingUtil
来简化
对于Activity 使用 DataBindingUtil.setContentView()
,其它的都可以使用 DataBindingUtil.inflate()
有些场景中,可能 UI-组件为null而报错了。如,混合webView时,在js回调中,再调用UI组件,这时宿主Activity可能已经finish了,而js回调开始执行
那就需要定义一个可空类型的 ViewDataBinding
实例protected val _bind: VB? = mBind
最后
以上就是清脆发带为你收集整理的Android 使用DataBindingUtil 封装支持DataBinding的BaseActivity、BaseFragment历程viewBinding 支持Databinding 支持使用 DataBindingUtil 封装简化的全部内容,希望文章能够帮你解决Android 使用DataBindingUtil 封装支持DataBinding的BaseActivity、BaseFragment历程viewBinding 支持Databinding 支持使用 DataBindingUtil 封装简化所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复