diff --git a/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameActivity.kt b/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameActivity.kt index 8b7c476..0cc6b36 100644 --- a/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameActivity.kt +++ b/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameActivity.kt @@ -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 : AppCompatActivity(), FrameView { protected val mBinding: VB by lazy(mode = LazyThreadSafetyMode.NONE) { - val vbClass: Class = - (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class - 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 = - (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[1] as Class - ViewModelProvider(this).get(vmClass) + BindingReflex.reflexViewModel(javaClass, this) } override fun onCreate(savedInstanceState: Bundle?) { diff --git a/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameFragment.kt b/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameFragment.kt index c90dbcc..56fc7b7 100644 --- a/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameFragment.kt +++ b/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameFragment.kt @@ -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 : Fragment(), FrameView { protected val mBinding: VB by lazy(mode = LazyThreadSafetyMode.NONE) { - val vbClass: Class = - (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class - 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 = - (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[1] as Class - ViewModelProvider(this).get(vmClass) + BindingReflex.reflexViewModel(javaClass, this) } override fun onCreateView( diff --git a/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameNotMVVMActivity.kt b/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameNotMVVMActivity.kt index bdf41ca..af3b736 100644 --- a/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameNotMVVMActivity.kt +++ b/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameNotMVVMActivity.kt @@ -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 : AppCompatActivity(), FrameNotMVVMView { protected val mBinding: VB by lazy(mode = LazyThreadSafetyMode.NONE) { - val vbClass: Class = - (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class - val inflate = vbClass.getDeclaredMethod("inflate", LayoutInflater::class.java) - inflate.invoke(null, layoutInflater) as VB + BindingReflex.reflexViewBinding(javaClass, layoutInflater) } override fun onCreate(savedInstanceState: Bundle?) { diff --git a/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameNotMVVMFragment.kt b/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameNotMVVMFragment.kt index 1cc6ee9..0efb997 100644 --- a/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameNotMVVMFragment.kt +++ b/Lib_Base/src/main/java/com/quyunshuo/base/mvvm/v/BaseFrameNotMVVMFragment.kt @@ -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 : Fragment(), FrameNotMVVMView { protected val mBinding: VB by lazy(mode = LazyThreadSafetyMode.NONE) { - val vbClass: Class = - (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class - val inflate = vbClass.getDeclaredMethod("inflate", LayoutInflater::class.java) - inflate.invoke(null, layoutInflater) as VB + BindingReflex.reflexViewBinding(javaClass, layoutInflater) } override fun onCreateView( diff --git a/Lib_Base/src/main/java/com/quyunshuo/base/utils/BindingReflex.kt b/Lib_Base/src/main/java/com/quyunshuo/base/utils/BindingReflex.kt new file mode 100644 index 0000000..a344d01 --- /dev/null +++ b/Lib_Base/src/main/java/com/quyunshuo/base/utils/BindingReflex.kt @@ -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 ViewBinding 实现类 + * @param aClass 当前类 + * @param from layouinflater + * @return viewBinding实例 + */ + fun 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 + if (ViewBinding::class.java.isAssignableFrom(tClass)) { + val inflate = tClass.getMethod("inflate", LayoutInflater::class.java) + return inflate.invoke(null, from) as V + } + } + return reflexViewBinding(aClass.superclass, from) + } catch (e: NoSuchMethodException) { + e.printStackTrace() + } catch (e: IllegalAccessException) { + e.printStackTrace() + } catch (e: InvocationTargetException) { + e.printStackTrace() + } + throw RuntimeException("ViewBinding初始化失败") + } + + /** + * 反射获取ViewBinding\ + */ + fun 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 + 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(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 ViewModel实现类 + * @param aClass 当前class + * @param owner 生命周期管理 + * @return ViewModel实例 + */ + fun 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 + if (ViewModel::class.java.isAssignableFrom(tClass)) { + return ViewModelProvider(owner)[tClass] + } + } + return reflexViewModel(aClass.superclass, owner) + } catch (e: Exception) { + e.printStackTrace() + } + throw RuntimeException("ViewModel初始化失败") + } + + /** + * 反射获取ViewModel,这个方法只提供给fragment使用. + * 如果fragment的父Activity有相同的ViewModel 那么生成的ViewModel将会是同一个实例,做到Fragment与Activity的数据同步, + * 或者说是同一个Activity中的多个Fragment同步使用用一个ViewModel达到数据之间的同步。 + * + * @param ViewModel实现类 + * @param aClass 当前class + * @param fragment fragment 调用 [Fragment.requireActivity] 方法 + * @return ViewModel实例 + */ + fun 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 + if (ViewModel::class.java.isAssignableFrom(tClass)) { + return ViewModelProvider(fragment.requireActivity())[tClass] + } + } + return reflexViewModelShared(aClass.superclass, fragment) + } catch (e: Exception) { + e.printStackTrace() + } + throw RuntimeException("ViewModel初始化失败") + } +} \ No newline at end of file