8月 242016
app上线前遇到一个很诡异的问题,同一款型号的手机,一台手机没问题,另一台手机则在显示首页后假死、然后直接闪退。经过排查,确定是自定义GridView惹的祸,异常信息如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | java.lang.IllegalArgumentException: parameter must be a descendant of this view at android.view.ViewGroup.offsetRectBetweenParentAndChild(ViewGroup.java: 5353 ) at android.view.ViewGroup.offsetDescendantRectToMyCoords(ViewGroup.java: 5282 ) at android.view.ViewGroup$ViewLocationHolder.init(ViewGroup.java: 7755 ) at android.view.ViewGroup$ViewLocationHolder.obtain(ViewGroup.java: 7689 ) at android.view.ViewGroup$ChildListForAccessibility.init(ViewGroup.java: 7624 ) at android.view.ViewGroup$ChildListForAccessibility.obtain(ViewGroup.java: 7592 ) at android.view.ViewGroup.addChildrenForAccessibility(ViewGroup.java: 1927 ) at android.view.ViewGroup.onInitializeAccessibilityNodeInfoInternal(ViewGroup.java: 2982 ) at android.widget.AdapterView.onInitializeAccessibilityNodeInfoInternal(AdapterView.java: 983 ) at android.widget.AbsListView.onInitializeAccessibilityNodeInfoInternal(AbsListView.java: 1509 ) at android.widget.GridView.onInitializeAccessibilityNodeInfoInternal(GridView.java: 2361 ) at android.view.View.onInitializeAccessibilityNodeInfo(View.java: 6151 ) at android.view.View.createAccessibilityNodeInfoInternal(View.java: 6110 ) at android.view.View.createAccessibilityNodeInfo(View.java: 6095 ) at android.view.accessibility.AccessibilityRecord.setSource(AccessibilityRecord.java: 145 ) at android.view.accessibility.AccessibilityRecord.setSource(AccessibilityRecord.java: 119 ) at android.view.View.onInitializeAccessibilityEventInternal(View.java: 6047 ) at android.widget.AdapterView.onInitializeAccessibilityEventInternal(AdapterView.java: 994 ) at android.view.View.onInitializeAccessibilityEvent(View.java: 6035 ) at android.view.View.sendAccessibilityEventUncheckedInternal(View.java: 5896 ) at android.view.View.sendAccessibilityEventUnchecked(View.java: 5881 ) at android.view.View$SendViewStateChangedAccessibilityEvent.run(View.java: 22468 ) at android.os.Handler.handleCallback(Handler.java: 743 ) at android.os.Handler.dispatchMessage(Handler.java: 95 ) at android.os.Looper.loop(Looper.java: 150 ) at android.app.ActivityThread.main(ActivityThread.java: 5546 ) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java: 794 ) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java: 684 ) |
直接在网上搜这个异常信息,会出来类似的问题,比如这个帖子,这些帖子给出的异常信息相似,最后给出的解决方案也类似,都是说焦点问题,只要调用clearFocus就可以了(这个清楚焦点的操作可以在多个地方进行),但我都试过,发现这些方法都没法解决我遇到的问题。后来通过同事试用app反馈,发现只要打开android系统的辅助功能(android accessibility 比如开关控制、放大手势之类的,不同手机菜单名可能不一样,比如MIUI中是在“无障碍”中的那些功能),就会出现这个问题。然后重新搜,发现是“检测窗口内容(检查您正与其他互动的窗口的内容)”这个功能导致的,在React项目也存在该问题,参考如下链接 传送门 以我的使用场景为例,在我修改GridView后,添加view似乎并不是像其他控件那样,把新添加的View加到整个ViewTree中,而使用辅助功能时,需要从ViewTree的根遍历到所有叶子View,到GridView这一层没法往下走,才导致了上述问题。实际上,看异常也可以看到是在涉及accessibility相关方法时出错,所以只要在GridView中添加如下代码即可解决:
1 2 3 4 5 | @Override public void addChildrenForAccessibility(ArrayList<View> outChildren) { // Explicitly override this to prevent accessibility events being passed down to children // Those will be handled by the mHostView which lives in the dialog } |