Android 使用DataBindingUtil 封装支持DataBinding的BaseActivityBaseFragment
Posted 匆忙拥挤repeat
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 使用DataBindingUtil 封装支持DataBinding的BaseActivityBaseFragment相关的知识,希望对你有一定的参考价值。
文章目录
历程
先是 使用了 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的BaseActivityBaseFragment的主要内容,如果未能解决你的问题,请参考以下文章
Android 使用DataBindingUtil 封装支持DataBinding的BaseActivityBaseFragment
Android 数据绑定 DatabindingUtil 与绑定类
`DataBindingUtil` 中的 `bind`、`inflate` 和 `setContentView` 有啥区别