反射初始化封装

This commit is contained in:
Dboy
2020-12-18 23:29:48 +08:00
parent 57e13ba9e5
commit a1688520af
5 changed files with 148 additions and 25 deletions

View File

@ -1,15 +1,13 @@
package com.quyunshuo.base.mvvm.v
import android.os.Bundle
import android.view.LayoutInflater
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.viewbinding.ViewBinding
import com.alibaba.android.arouter.launcher.ARouter
import com.quyunshuo.base.utils.BindingReflex
import com.quyunshuo.base.utils.EventBusRegister
import com.quyunshuo.base.utils.EventBusUtils
import java.lang.reflect.ParameterizedType
/**
* @Author: QuYunShuo
@ -21,16 +19,11 @@ abstract class BaseFrameActivity<VB : ViewBinding, VM : ViewModel> :
AppCompatActivity(), FrameView<VB> {
protected val mBinding: VB by lazy(mode = LazyThreadSafetyMode.NONE) {
val vbClass: Class<VB> =
(javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<VB>
val inflate = vbClass.getDeclaredMethod("inflate", LayoutInflater::class.java)
inflate.invoke(null, layoutInflater) as VB
BindingReflex.reflexViewBinding(javaClass, layoutInflater)
}
protected val mViewModel: VM by lazy(mode = LazyThreadSafetyMode.NONE) {
val vmClass: Class<VM> =
(javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[1] as Class<VM>
ViewModelProvider(this).get(vmClass)
BindingReflex.reflexViewModel(javaClass, this)
}
override fun onCreate(savedInstanceState: Bundle?) {

View File

@ -9,6 +9,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.viewbinding.ViewBinding
import com.alibaba.android.arouter.launcher.ARouter
import com.quyunshuo.base.utils.BindingReflex
import com.quyunshuo.base.utils.EventBusRegister
import com.quyunshuo.base.utils.EventBusUtils
import java.lang.reflect.ParameterizedType
@ -22,15 +23,11 @@ import java.lang.reflect.ParameterizedType
abstract class BaseFrameFragment<VB : ViewBinding, VM : ViewModel> : Fragment(), FrameView<VB> {
protected val mBinding: VB by lazy(mode = LazyThreadSafetyMode.NONE) {
val vbClass: Class<VB> =
(javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<VB>
val inflate = vbClass.getDeclaredMethod("inflate", LayoutInflater::class.java)
inflate.invoke(null, layoutInflater) as VB
BindingReflex.reflexViewBinding(javaClass, layoutInflater)
}
protected val mViewModel: VM by lazy(mode = LazyThreadSafetyMode.NONE) {
val vmClass: Class<VM> =
(javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[1] as Class<VM>
ViewModelProvider(this).get(vmClass)
BindingReflex.reflexViewModel(javaClass, this)
}
override fun onCreateView(

View File

@ -5,6 +5,7 @@ import android.view.LayoutInflater
import androidx.appcompat.app.AppCompatActivity
import androidx.viewbinding.ViewBinding
import com.alibaba.android.arouter.launcher.ARouter
import com.quyunshuo.base.utils.BindingReflex
import com.quyunshuo.base.utils.EventBusRegister
import com.quyunshuo.base.utils.EventBusUtils
import java.lang.reflect.ParameterizedType
@ -19,10 +20,7 @@ abstract class BaseFrameNotMVVMActivity<VB : ViewBinding> : AppCompatActivity(),
FrameNotMVVMView<VB> {
protected val mBinding: VB by lazy(mode = LazyThreadSafetyMode.NONE) {
val vbClass: Class<VB> =
(javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<VB>
val inflate = vbClass.getDeclaredMethod("inflate", LayoutInflater::class.java)
inflate.invoke(null, layoutInflater) as VB
BindingReflex.reflexViewBinding(javaClass, layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {

View File

@ -7,6 +7,7 @@ import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.viewbinding.ViewBinding
import com.alibaba.android.arouter.launcher.ARouter
import com.quyunshuo.base.utils.BindingReflex
import com.quyunshuo.base.utils.EventBusRegister
import com.quyunshuo.base.utils.EventBusUtils
import java.lang.reflect.ParameterizedType
@ -20,10 +21,7 @@ import java.lang.reflect.ParameterizedType
abstract class BaseFrameNotMVVMFragment<VB : ViewBinding> : Fragment(), FrameNotMVVMView<VB> {
protected val mBinding: VB by lazy(mode = LazyThreadSafetyMode.NONE) {
val vbClass: Class<VB> =
(javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<VB>
val inflate = vbClass.getDeclaredMethod("inflate", LayoutInflater::class.java)
inflate.invoke(null, layoutInflater) as VB
BindingReflex.reflexViewBinding(javaClass, layoutInflater)
}
override fun onCreateView(

View File

@ -0,0 +1,137 @@
package com.quyunshuo.base.utils
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStoreOwner
import androidx.viewbinding.ViewBinding
import java.lang.RuntimeException
import java.lang.reflect.InvocationTargetException
import java.lang.reflect.ParameterizedType
import java.util.*
/**
* @author DBoy
* @date 2020/9/29
* Class 描述 : 用于反射获取 ViewModel 和 ViewBinding
*/
object BindingReflex {
/**
* 反射获取ViewBinding
*
* @param <V> ViewBinding 实现类
* @param aClass 当前类
* @param from layouinflater
* @return viewBinding实例
</V> */
fun <V : ViewBinding> reflexViewBinding(aClass: Class<*>, from: LayoutInflater?): V {
try {
val actualTypeArguments =
(Objects.requireNonNull(aClass.genericSuperclass) as ParameterizedType).actualTypeArguments
for (i in actualTypeArguments.indices) {
val tClass = actualTypeArguments[i] as Class<V>
if (ViewBinding::class.java.isAssignableFrom(tClass)) {
val inflate = tClass.getMethod("inflate", LayoutInflater::class.java)
return inflate.invoke(null, from) as V
}
}
return reflexViewBinding<V>(aClass.superclass, from)
} catch (e: NoSuchMethodException) {
e.printStackTrace()
} catch (e: IllegalAccessException) {
e.printStackTrace()
} catch (e: InvocationTargetException) {
e.printStackTrace()
}
throw RuntimeException("ViewBinding初始化失败")
}
/**
* 反射获取ViewBinding\
*/
fun <V : ViewBinding> reflexViewBinding(
aClass: Class<*>,
from: LayoutInflater?,
viewGroup: ViewGroup?,
b: Boolean
): V {
try {
val actualTypeArguments =
(Objects.requireNonNull(aClass.genericSuperclass) as ParameterizedType).actualTypeArguments
for (i in actualTypeArguments.indices) {
val tClass = actualTypeArguments[i] as Class<V>
if (ViewBinding::class.java.isAssignableFrom(tClass)) {
val inflate = tClass.getDeclaredMethod(
"inflate",
LayoutInflater::class.java,
ViewGroup::class.java,
Boolean::class.javaPrimitiveType
)
return inflate.invoke(null, from, viewGroup, b) as V
}
}
return reflexViewBinding<ViewBinding>(aClass.superclass, from, viewGroup, b) as V
} catch (e: NoSuchMethodException) {
e.printStackTrace()
} catch (e: IllegalAccessException) {
e.printStackTrace()
} catch (e: InvocationTargetException) {
e.printStackTrace()
}
throw RuntimeException("ViewBinding初始化失败")
}
/**
* 反射获取ViewModel
*
* @param <VM> ViewModel实现类
* @param aClass 当前class
* @param owner 生命周期管理
* @return ViewModel实例
</VM> */
fun <VM : ViewModel> reflexViewModel(aClass: Class<*>, owner: ViewModelStoreOwner): VM {
try {
val actualTypeArguments =
(Objects.requireNonNull(aClass.genericSuperclass) as ParameterizedType).actualTypeArguments
for (i in actualTypeArguments.indices) {
val tClass = actualTypeArguments[i] as Class<VM>
if (ViewModel::class.java.isAssignableFrom(tClass)) {
return ViewModelProvider(owner)[tClass]
}
}
return reflexViewModel<VM>(aClass.superclass, owner)
} catch (e: Exception) {
e.printStackTrace()
}
throw RuntimeException("ViewModel初始化失败")
}
/**
* 反射获取ViewModel,这个方法只提供给fragment使用.
* 如果fragment的父Activity有相同的ViewModel 那么生成的ViewModel将会是同一个实例做到Fragment与Activity的数据同步,
* 或者说是同一个Activity中的多个Fragment同步使用用一个ViewModel达到数据之间的同步。
*
* @param <VM> ViewModel实现类
* @param aClass 当前class
* @param fragment fragment 调用 [Fragment.requireActivity] 方法
* @return ViewModel实例
</VM> */
fun <VM : ViewModel> reflexViewModelShared(aClass: Class<*>, fragment: Fragment): VM {
try {
val actualTypeArguments =
(Objects.requireNonNull(aClass.genericSuperclass) as ParameterizedType).actualTypeArguments
for (i in actualTypeArguments.indices) {
val tClass = actualTypeArguments[i] as Class<VM>
if (ViewModel::class.java.isAssignableFrom(tClass)) {
return ViewModelProvider(fragment.requireActivity())[tClass]
}
}
return reflexViewModelShared<VM>(aClass.superclass, fragment)
} catch (e: Exception) {
e.printStackTrace()
}
throw RuntimeException("ViewModel初始化失败")
}
}