目录
一、前言
本文提供了一个基类,通过继承基类和传入
泛型类
型就可以实现创建ViewModel和绑定ViewDataBinding的工作。
二、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 版权协议,转载请附上原文出处链接和本声明。