起因
前一段时间比较空闲,于是就把Android的MVVM给封装了一下。在我的框架里面‘vm’这个参数是肯定存在的,但是又不想在业务逻辑中进行赋值vm。于是乎就通过反射的方式在BaseActivity中通过反射的方式来进行处理了。在Debug版本跑的飞起,在准备上uat 版本的时候出现了闪退的问题。
先说解决方案
在 proguard-rules.pro 排除这2块的混淆
-keep class **.*Binding {*;}
-keep class **.*BindingImpl {*;}
PS:
我这里直接把整个类都进行了排除混淆,严谨一点的应该单独配置 setVm的方法的混淆
排查过程
首先查看报错信息,发现是我自定义的BindingAdapter 空针问题,当时以为我传入的 实体类出现了混淆问题,把实体给排除混淆发现没有问题。 那么引用 ‘vm.scanStatus’为空 会不会直接原因就是vm为空?(代码①)
后面进行了代码测试,果然vm为空。那么进行业务层面的主动赋值会不会就OK了呢?答案是肯定的,是OK了的。那么原因就很明显了,肯定就是我反射的时候寻找setVm的方法是被混淆掉了。
原因找到了,那么剩下就是解决的方案了,我们知道的 在DataBinding中的layout会被映射到 xxxBinding上,而相关实现就在xxxBindingImpl上。那么把这2块的混淆给去掉不就ok了吗?加上混淆试一下 果然好用
部分源码
代码①
<TextView
android:id="@+id/connect_step_3"
style="@style/AppTextView.Connect.Step"
bindIWarmErrorStep3="@{vm.scanStatus}"
android:text="@string/connect_step_3" />
@JvmStatic
@BindingAdapter(value = ["bindError"], requireAll = false)
fun bindError(view: TextView, status: Status) {
when (status) {
Status.NotFound -> {
view.visibility = View.VISIBLE
view.setText(R.string.unfind)
}
Status.ConnectedFailed -> {
view.visibility = View.VISIBLE
view.setText(R.string.connect_failed)
}
else -> view.visibility = View.GONE
}
}
代码②
protected open fun initViewModel(vm: VM) {
val activity = this@BindActivity
// dataBinding 设置vm参数
ReflectionUtils.invokeMethod(dataBinding, "setVm", vm, viewModelClass)
vm.loadingStatus.observe(activity, Observer { changeLoadingStatus(it) })
vm.errorStatus.observe(activity, Observer { changeErrorStatus(it) })
vm.successStatus.observe(activity, Observer { changeSuccessStatus(it) })
vm.emptyStatus.observe(activity, Observer { changeEmptyStatus(it) })
vm.toastMessage.observe(activity, Observer { showToast(it) })
}
网友评论