Android ViewBinding 基类两种写法

554 阅读2分钟

这两段代码的目的是一样的,都是通过反射获取 ViewBinding 类的 inflate 方法并调用它来初始化 ViewBinding 实例。主要区别在于获取 ViewBinding 类的方式和代码的结构。

第一段代码

val bindingClass = getViewBindingClass()
val method = bindingClass.getMethod("inflate", LayoutInflater::class.java, ViewGroup::class.java, Boolean::class.java)
mVB = method.invoke(null, inflater, container, false) as VB

代码示例


    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // 自定义了视图的创建过程,因此不需要调用父类的onCreateView方法
        // super.onCreateView(inflater, container, savedInstanceState)
        val bindingClass = getViewBindingClass()
        val method = bindingClass.getMethod("inflate", LayoutInflater::class.java, ViewGroup::class.java, Boolean::class.java)
        mVB = method.invoke(null, inflater, container, false) as VB

        // check if the view binding is inflated
        LogUtils.i("BaseHybridPowerFragment", "ViewBinding inflated: ${_binding != null}")

        return mVB.root
    }


    abstract fun getViewBindingClass(): Class<VB>

解释

  1. getViewBindingClass() 是一个假设的方法,用于获取 ViewBinding 类的 Class 对象。
  2. 通过 bindingClass.getMethod 获取 inflate 方法。
  3. 调用 method.invoke 来初始化 ViewBinding 实例。

这种方式更灵活,因为你可以在 getViewBindingClass() 方法中自定义获取 ViewBinding 类的逻辑,适应不同的需求。

第二段代码

val type = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<VB>
val method = type.getMethod("inflate", LayoutInflater::class.java, ViewGroup::class.java, Boolean::class.java)
_binding = method.invoke(null, inflater, container, false) as VB

代码示例

abstract class BaseFragment<VB : ViewBinding> : Fragment() { 
    private var _binding: VB? = null 
    protected val binding get() = _binding!! 
    
    override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { 
    
        // 通过反射获取 ViewBinding 的 inflate 方法并调用 
        val type = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<VB> 
        val method = type.getMethod("inflate", LayoutInflater::class.java, ViewGroup::class.java, Boolean::class.java) 
        _binding = method.invoke(null, inflater, container, false) as VB return binding.root 
    } 
    
    override fun onDestroyView() { 
        super.onDestroyView() _binding = null 
        } 
   }

解释

  1. 通过 javaClass.genericSuperclass 获取当前类的泛型参数类型。
  2. 将泛型参数类型转换为 Class<VB> 对象。
  3. 通过 type.getMethod 获取 inflate 方法。
  4. 调用 method.invoke 来初始化 ViewBinding 实例。

这种方式直接从泛型参数中获取 ViewBinding 类的类型,代码更简洁,但依赖于泛型参数的存在和正确配置。

总结

  • 第一段代码 更灵活,可以通过 getViewBindingClass() 方法自定义获取 ViewBinding 类的逻辑,适应不同的需求。
  • 第二段代码 更简洁,直接通过泛型参数获取 ViewBinding 类的类型,但依赖于泛型参数的正确配置。

选择哪种方式取决于你的具体需求和代码结构。如果你的 BaseFragment 设计中泛型参数类型总是正确配置,那么第二种方式更为简洁。如果你需要更灵活的方式来获取 ViewBinding 类,那么第一种方式更合适。