背景:
今天项目中遇到一个奇葩问题,给NestedScrollView子view1,view2设置 GONE属性的时候,发现留下了两个空白区域(如下图所示)。我们都知道view的GONE属性是会把整个区域都会给隐藏掉的呀,一头雾水,why?
分析:
绞尽脑汁。。。没办法只能一步一步debug,尝试不断复现此问题,然后抓log,说来也巧被我抓住了一些蛛丝马迹。
2020-12-08 14:35:55.275 15880-15898/? W/System.err: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
2020-12-08 14:35:55.275 15880-15898/? W/System.err: at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:8384)
2020-12-08 14:35:55.275 15880-15898/? W/System.err: at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1476)
2020-12-08 14:35:55.275 15880-15898/? W/System.err: at android.view.View.requestLayout(View.java:24528)
2020-12-08 14:35:55.275 15880-15898/? I/chatty: uid=10573(com.jiqid.ipen) Binder:15880_3 identical 4 lines
2020-12-08 14:35:55.275 15880-15898/? W/System.err: at android.view.View.requestLayout(View.java:24528)
2020-12-08 14:35:55.275 15880-15898/? W/System.err: at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:380)
2020-12-08 14:35:55.275 15880-15898/? W/System.err: at android.view.View.requestLayout(View.java:24528)
2020-12-08 14:35:55.275 15880-15898/? I/chatty: uid=10573(com.jiqid.ipen) Binder:15880_3 identical 3 lines
2020-12-08 14:35:55.275 15880-15898/? W/System.err: at android.view.View.requestLayout(View.java:24528)
2020-12-08 14:35:55.275 15880-15898/? W/System.err: at androidx.core.widget.NestedScrollView.requestLayout(NestedScrollView.java:1782)
2020-12-08 14:35:55.275 15880-15898/? W/System.err: at android.view.View.requestLayout(View.java:24528)
2020-12-08 14:35:55.275 15880-15898/? I/chatty: uid=10573(com.jiqid.ipen) Binder:15880_3 identical 1 line
2020-12-08 14:35:55.275 15880-15898/? W/System.err: at android.view.View.requestLayout(View.java:24528)
2020-12-08 14:35:55.275 15880-15898/? W/System.err: at androidx.recyclerview.widget.RecyclerView.requestLayout(RecyclerView.java:4202)
2020-12-08 14:35:55.275 15880-15898/? W/System.err: at androidx.recyclerview.widget.RecyclerView$RecyclerViewDataObserver.onChanged(RecyclerView.java:5286)
2020-12-08 14:35:55.275 15880-15898/? W/System.err: at androidx.recyclerview.widget.RecyclerView$AdapterDataObservable.notifyChanged(RecyclerView.java:11997)
2020-12-08 14:35:55.275 15880-15898/? W/System.err: at androidx.recyclerview.widget.RecyclerView$Adapter.notifyDataSetChanged(RecyclerView.java:7070)
2020-12-08 14:35:55.275 15880-15898/? W/System.err: at com.jiqid.ipen.view.base.BaseRecyclerAdapter.setItems(BaseRecyclerAdapter.java:65)
2020-12-08 14:35:55.275 15880-15898/? W/System.err: at com.jiqid.ipen.view.fragment.MyFragment.queryDevices(MyFragment.java:303)
2020-12-08 14:35:55.276 15880-15898/? W/System.err: at com.jiqid.ipen.view.fragment.MyFragment.access$600(MyFragment.java:98)
2020-12-08 14:35:55.276 15880-15898/? W/System.err: at com.jiqid.ipen.view.fragment.MyFragment$5.querySuccess(MyFragment.java:739)
2020-12-08 14:35:55.276 15880-15898/? W/System.err: at com.jiqid.ipen.model.manager.DeviceAndBabyManager.progressResult(DeviceAndBabyManager.java:104)
2020-12-08 14:35:55.276 15880-15898/? W/System.err: at com.jiqid.ipen.model.manager.DeviceAndBabyManager.access$000(DeviceAndBabyManager.java:34)
2020-12-08 14:35:55.276 15880-15898/? W/System.err: at com.jiqid.ipen.model.manager.DeviceAndBabyManager$1$1.onSucceed(DeviceAndBabyManager.java:66)
2020-12-08 14:35:55.276 1073-16024/? E/ResolverController: No valid NAT64 prefix (125, <unspecified>/0)
2020-12-08 14:35:55.276 15880-15898/? W/System.err: at com.miot.api.DeviceManager$DeviceListener.onSucceed(DeviceManager.java:159)
2020-12-08 14:35:55.276 15880-15898/? W/System.err: at com.miot.api.IDeviceHandler$Stub.onTransact(IDeviceHandler.java:59)
2020-12-08 14:35:55.276 15880-15898/? W/System.err: at android.os.Binder.execTransactInternal(Binder.java:1021)
2020-12-08 14:35:55.276 15880-15898/? W/System.err: at android.os.Binder.execTransact(Binder.java:994)
当看见这段日志后眼前一亮,感叹终于发现了问题,但是仍然不知道为什么会出现这个问题,从程序员专业的角度来说:“不可能的,我的代码怎么可能会出现这种问题。。。巴拉巴拉“。冷静,保持冷静
从字面意思来看是说只有创建视图层次结构的原始线程才可以更新它的视图,于是按照这个提示,在对应的位置queryDevices()中加入测试代码Thread.currentThread().getId(),根据打印数据发现偶尔该方法不是执行在UI线程中的,多次测试发现如果不在UI线程中就会报如上图异常日志,页面就会出现文章开头所讲述的错乱状况。
解决:
问题分析清楚以后修改起来就比较简单了
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mDeviceInfoAdapter.setItems(deviceBeans);
}
});
总结:
遇到bug不要慌,稳步分析加log,bug一旦露头来,认真解决不要烦。