简化ViewModel和ViewDataBinding的创建工作-Kotlin版

  • Post author:
  • Post category:其他



目录


一、前言


二、ViewDataBinding


2.1 ViewDataBindingHelper


2.2 Activity中使用


2.3 Fragment中使用


2.4 RecyclerView.Adapter中使用


三、ViewModel


3.1 ViewModelHelper


3.2 基类中使用


一、前言

本文提供了一个基类,通过继承基类和传入

泛型类

型就可以实现创建ViewModel和绑定ViewDataBinding的工作。


Java版看这里

二、ViewDataBinding


2.1 ViewDataBindingHelper

object ViewDataBindingHelper {

    /**
     * 获取指定的 [viewBindingClass] 实例
     * @param viewBindingClass Class<T> ViewDataBinding的子类
     * @param context Context 上下文
     * @param parent ViewGroup 父视图容器
     * @return T?
     */
    fun <T : ViewDataBinding> inflateVDB(
        viewBindingClass: Class<T>,
        context: Context,
        parent: ViewGroup,
    ): T? {
        try {
            val inflate: Method? = viewBindingClass?.getDeclaredMethod("inflate",
                LayoutInflater::class.java,
                ViewGroup::class.java,
                Boolean::class.java)
            return inflate?.invoke(null,
                LayoutInflater.from(context),
                parent,
                false) as? T
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return null
    }

    /**
     * 获取[kClass]的泛型参数中的ViewDataBinding子类实例
     * @param context Context
     * @param kClass KClass<*>
     * @return ViewDataBinding?
     */
    fun inflateVDB(
        context: Context,
        kClass: KClass<*>,
    ): ViewDataBinding? {
        try {
            val clazz = getViewDataBindingClass(kClass)
            val inflate: Method? = clazz?.getDeclaredMethod(
                "inflate",
                LayoutInflater::class.java,
            )
            return inflate?.invoke(null, LayoutInflater.from(context)) as? ViewDataBinding
        } catch (e: Exception) {

            e.printStackTrace()
        }
        return null
    }


    /**
     * 返回给定类及其父类中泛型参数中的首个ViewDatabinding子类
     * @param kClass KClass<*>
     * @return Class<ViewDataBinding>?
     */
    private fun getViewDataBindingClass(kClass: KClass<*>): Class<ViewDataBinding>? {
        val type = kClass.java.genericSuperclass ?: return null
        if (type is ParameterizedType) {
            type.actualTypeArguments.forEach {
                if (it is Class<*> && isSubClassOfViewDataBinding(it)) return it as Class<ViewDataBinding>
            }
        }
        for (subKClass in kClass.superclasses) {
            return getViewDataBindingClass(subKClass)
        }
        return null
    }

    /**
     * 判断一个类是否继承Viewdatabinding
     * @param clazz Class<*>?
     * @return Boolean
     */
    private fun isSubClassOfViewDataBinding(clazz: Class<*>?): Boolean {
        if (clazz == null) return false
        return ViewDataBinding::class.java.isAssignableFrom(clazz)
    }

}


2.2 Activity中使用

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ...
        mBinding= ViewDataBindingHelper.inflateVDB(baseContext,this::class) as VDB
        setContentView(mBinding.root)
        ...
    }


2.3 Fragment中使用

  override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?,
    ): View {
        mBinding = ViewDataBindingHelper.inflateVDB(requireContext(), this::class) as VDB
        mBinding.lifecycleOwner = this.viewLifecycleOwner
        return mBinding.root
    }

2.4 RecyclerView.Adapter中使用

 internal fun <T : ViewDataBinding> createViewDataBinding(
        clazz: Class<T>,
        parent: ViewGroup,
    ): T {
        return ViewDataBindingHelper.inflateVDB(clazz, parent.context, parent) as T
    }

 override fun onCreateViewHolder(
            parent: ViewGroup,
            viewType: Int,
        ): ViewHolder {
            return when (viewType) {
                TYPE_PLUGIN_ITEM -> {
                    val pluginItemBinding: PluginItemBinding =
                        createViewDataBinding(PluginItemBinding::class.java, parent)
                    ViewHolder(pluginItemBinding)
                }
                else -> {
                    val pluginItemHeaderBinding =
                        createViewDataBinding(PluginItemHeaderBinding::class.java, parent)
                    ViewHolder(pluginItemHeaderBinding)
                }
            }

        }

三、ViewModel

3.1 ViewModelHelper

object ViewModelHelper {
    fun createViewModel(owner: ViewModelStoreOwner, kClass: KClass<*>): ViewModel? {
        val clazz = getViewModelClass(kClass);
        return if (clazz != null)
            ViewModelProvider(owner).get(clazz)
        else null
    }

    private fun getViewModelClass(kClass: KClass<*>): Class<ViewModel>? {
        val type = kClass.java.genericSuperclass ?: return null
        if (type is ParameterizedType) {
            type.actualTypeArguments.forEach {
                if (it is Class<*> && isSubClassOfViewModel(it))
                    return it as Class<ViewModel>
            }
        }
        for (subKClass in kClass.superclasses) {
            return getViewModelClass(subKClass)
        }
        return null
    }

    private fun isSubClassOfViewModel(clazz: Class<*>?): Boolean {
        if (clazz == null)
            return false
        return ViewModel::class.java.isAssignableFrom(clazz)
    }
}

3.2 基类中使用

   open fun createViewModel(): VM {
        return ViewModelHelper.createViewModel(this, this::class) as VM
    }

   override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mViewModel = createViewModel()
    }



版权声明:本文为jokers9221原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。