1.引言
日常开发, 相信我们对于Activity都有自己的BaseActivity, 那么在引入JetPack后, 如何使我们的BaseActivity简洁且高效成了值得思考的问题
- 涉及的技术栈
MVVM, JetPack, LiveData, DataBing, ViewModel - 先来看看最后的效果
是不是很简洁…
2. 如何实现
- MainActivity继承自BaseActivityVBVM
abstract class BaseActivityVBVM<VB : ViewDataBinding, VM : ViewModel> : BaseActivityVB<VB>, IViewDataBinding<VB> {
protected var _factory: ViewModelProvider.Factory?
/**
* 针对Hilt(@JvmOverloads kotlin默认参数值无效)
* @constructor
*/
constructor() : this(null)
constructor(factory: ViewModelProvider.Factory?) : super(){
_factory = factory
}
//
protected lateinit var vm: VM
//
@CallSuper
override fun initLayout() {
super.initLayout()
vm = UtilKViewModel.get(this, _factory/*, 1*/)
bindViewVM(vb)
}
}
vm是通过反射获得
- 再看BaseActivityVB
abstract class BaseActivityVB<VB : ViewDataBinding>(
/*protected var _factory: ViewModelProvider.Factory? = null*/
) : AppCompatActivity(), IActivity, IUtilK {
protected val vb: VB by lazy(mode = LazyThreadSafetyMode.NONE) {
UtilKViewDataBinding.get<VB>(this::class.java, layoutInflater/*, 0*/).apply {
lifecycleOwner = this@BaseActivityVB
}
}
///
@CallSuper
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
initFlag()
initLayout()
initData(savedInstanceState)
}
@CallSuper
override fun onDestroy() {
vb.unbind()
super.onDestroy()
}
///
@CallSuper
override fun initLayout() {
setContentView(vb.root)
}
@CallSuper
override fun initData(savedInstanceState: Bundle?) {
initView(savedInstanceState)
initObserver()
}
}
等等?!这就结束了,稍安勿躁,最精华的来了
VB和VM是怎么来的 --> 反射
- VM
@JvmStatic
@Suppress(CSuppress.UNCHECKED_CAST)
fun <VB : ViewDataBinding> get(clazz: Class<*>, inflater: LayoutInflater/*, index: Int = 0*/): VB =
UtilKReflectGenericKotlin.getParentGenericTypeByTClazz(clazz, ViewDataBinding::class.java)?.run {
getDeclaredMethod("inflate", LayoutInflater::class.java).invoke(null, inflater) as VB
} ?: throw Exception("inflate activity vb fail!")
- 由于多层继承, 我们还要考虑泛型的类型匹配
@JvmStatic
fun getParentGenericTypeByTClazz(clazz: Class<*>, parentClazz: Class<*>/*, index: Int = 0*/): Class<*>? =
getParentGenericTypeByT(clazz, parentClazz) as? Class<*>?
@JvmStatic
fun getParentGenericTypeByT(clazz: Class<*>, tClazz: Class<*>/*, index: Int = 0*/): Type? {
val superClazz: Class<*>? = clazz.superclass
val genericSuperclass: Type? = clazz.genericSuperclass
if (genericSuperclass !is ParameterizedType) {//当继承类不是参数化类型,就从父类中寻找
return if (superClazz != null) {
getParentGenericTypeByT(superClazz, tClazz)//当我们继承多层BaseActivity时递归查找泛型
} else
null
}
genericSuperclass.actualTypeArguments.filterIsInstance<Class<*>>()
.run {
this.printlog()//for debug
if (this.isNotEmpty()) {
for (clz in this) {
if (tClazz.isAssignableFrom(clz))
return clz
}
}
if (superClazz != null)
return getParentGenericTypeByT(superClazz, tClazz)
else
return null
}
}
3. 实际开发
@AndroidEntryPoint
class MainActivity : BaseActivityVBVM<ActivityMainBinding, MainViewModel>() {
override fun initView(savedInstanceState: Bundle?) {
}
override fun bindViewVM(vb: ActivityMainBinding) {
vb.vm = vm
}
}
@HiltViewModel
class MainViewModel @Inject constructor(private val _cache: Cache) : BaseViewModel() {
var number_gege by VarProperty_Set(_cache.number_gege) { field, value ->
lv_number_gege.value = value.toString()
_cache.number_gege = value
true
}
var number_meimei by VarProperty_Set(_cache.number_meimei) { field, value ->
lv_number_meimei.value = value.toString()
_cache.number_meimei = value
true
}
val lv_number_gege = MutableLiveData(_cache.number_gege.toString())
val lv_number_meimei = MutableLiveData(_cache.number_meimei.toString())
fun add_gege(other: Double) {
number_gege = number_gege.toBigDecimal().add(BigDecimal(other)).toDouble()
}
fun minus_gege(other: Double) {
number_gege = number_gege.toBigDecimal().minus(BigDecimal(other)).toDouble()
}
fun add_meimei(other: Double) {
number_meimei = number_meimei.toBigDecimal().add(BigDecimal(other)).toDouble()
}
fun minus_meimei(other: Double) {
number_meimei = number_meimei.toBigDecimal().minus(BigDecimal(other)).toDouble()
}
}
bingo这就是所有的代码,等等, 还有的是不是没贴,莫担心, 热乎的开源地址为下
1.图中库的开源地址: SwiftKit
1.图中示例项目的开源地址: LoveCalculator