如何解决ViewDataBinding会导致Activity.finish和NPE在查看附件期间访问mRebindRunnable之后恢复应用程序崩溃
成功启动活动后崩溃,使带有数据绑定的片段膨胀。在根级别上按“后退”按钮后,该应用程序(正确地)经过activity.finish()
,但将应用程序实例保留在后台。
重新启动后,该应用在创建视图后的某个时刻崩溃(至少基于调试)。
崩溃:
2020-08-26 20:00:50.626 9706-9706/com.org.app.dev E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.org.app.dev,PID: 9706
java.lang.NullPointerException: Attempt to read from field 'java.lang.Runnable androidx.databinding.ViewDataBinding.mRebindRunnable' on a null object reference
at androidx.databinding.ViewDataBinding.access$100(ViewDataBinding.java:65)
at androidx.databinding.ViewDataBinding$6.onViewAttachedToWindow(ViewDataBinding.java:165)
at android.view.View.dispatchAttachedToWindow(View.java:19564)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3437)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3437)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3437)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3437)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3437)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3437)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3437)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3437)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3437)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3437)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3437)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2028)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1721)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7598)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:966)
at android.view.Choreographer.doCallbacks(Choreographer.java:790)
at android.view.Choreographer.doFrame(Choreographer.java:725)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:951)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
在深入研究源代码,进行调试时,我能收集的最好的信息是ViewDataBinding看到以前绑定的视图已重新连接,并尝试与现有资源重新绑定。但是,它显然丢失了对静态可运行对象的引用。来自ViewDataBinding的相对源代码:
private static final OnAttachStateChangeListener ROOT_REATTACHED_LISTENER;
static {
if (VERSION.SDK_INT < VERSION_CODES.KITKAT) {
ROOT_REATTACHED_LISTENER = null;
} else {
ROOT_REATTACHED_LISTENER = new OnAttachStateChangeListener() {
@TargetApi(VERSION_CODES.KITKAT)
@Override
public void onViewAttachedToWindow(View v) {
// execute the pending bindings.
final ViewDataBinding binding = getBinding(v);
binding.mRebindRunnable.run();
v.removeOnAttachStateChangeListener(this);
}
@Override
public void onViewDetachedFromWindow(View v) {
}
};
}
}
我确实注意到来自App crash caused by data binding related to java.lang.Runnable android.databinding.ViewDataBinding.mRebindRunnable的相同堆栈跟踪信息,但是该问题似乎是关于应用程序立即崩溃(我的代码仅在尝试补水后发生)的问题。但是从那个问题上,我确实注意到,记录我的视图标记返回空值。我尝试在xml中设置静态标签,而没有更改。
我尝试过的其他事情:
- 如果仅实例化片段,则不会发生此问题(但显然不会附加到框架布局上
- 没有明确的调试崩溃点(onCreateView和onViewCreated都被调用)
- 我尝试过更改充气,分配生命周期所有者,绑定视图模型的方式;没有变化影响崩溃。
- 我尝试对绑定(invalidateAll(),unbind())进行一些调用,但均未成功。
同样,该问题仅在应用程序实例仍处于活动状态但活动已被破坏时才会出现。谢谢你的提示!
编辑:相关代码位
活动(Java)-
ExampleFragment exampleFragment = new ExampleFragment(exampleParameter);
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager
.beginTransaction()
.add(R.id.example_frame_layout,exampleFragment,EXAMPLE_TAG)
.commit();
片段(科特琳)-
override fun onCreateView(
inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?
): View? {
binding = FragmentExampleBinding.inflate(inflater,container,false).apply {
lifecycleOwner = viewLifecycleOwner
}
return binding.root
}
override fun onViewCreated(view: View,savedInstanceState: Bundle?) {
super.onViewCreated(view,savedInstanceState)
binding.run {
viewModel = this@ExampleFragment.viewModel
}
}
更新
有趣的是,当我尝试将同一片段(新实例化)充气到另一个(非启动)活动中时,我现在看到了这一点。调试这种情况,除了膨胀并返回绑定的根视图(而不是null)之后,我没有遇到任何崩溃。我尝试使用为布局创建的静态方法以及DataBindingUtil。两者都遇到相同的崩溃。
解决方法
尤里卡!
<merge/>
不仅不能用于<include/>
版式(在此处已记录:https://developer.android.com/topic/libraries/data-binding/expressions#includes)
但是
绑定也不能在以<include/>
为根的<merge/>
布局中使用。看起来像这样:
<layout>
...
<include layout="id/sub_layout"
bind:viewModel="@{viewModel} />
...
</layout>
问题(R.id.sub_layout.xml):
<layout>
...
<merge>
<TextView/>
<ImageView/>
</merge>
...
</layout>
奇怪的是,它似乎可以在发射活动中起作用,但是很高兴知道导致此现象的症状(通货膨胀后崩溃崩溃)。 对于那些在数据绑定和错误消息方面遇到麻烦的人,我绝对建议尝试更改您的布局。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。