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

目录

一、前言

二、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()
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值