社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
因为一直在参加比赛开发一款 APP ,然后今天在测试的时候发现了一个问题,即当打开进入 APP 后,走过以下路径
近期记录——》班级——》打开班级详情——》个人中心——》当前课堂 时(下面的动图为已修复后的路径演示),出现了软件闪退的情况。
经过查找,找到了软件崩溃时的错误记录如下:
2019-02-25 14:49:56.735 12007-12015/? E/art: Failed sending reply to debugger: Broken pipe
2019-02-25 14:49:57.580 12007-12042/? E/OpenGLRenderer: hwui_debug::CanvasContext createSurface sur=0x0, isValid =0
2019-02-25 14:49:58.807 12007-12042/com.example.smartclass E/OpenGLRenderer: hwui_debug::CanvasContext createSurface sur=0x0, isValid =0
2019-02-25 14:50:03.367 12007-12042/com.example.smartclass E/OpenGLRenderer: hwui_debug::CanvasContext createSurface sur=0x0, isValid =0
2019-02-25 14:50:10.292 12007-12007/com.example.smartclass E/FragmentManager: No view found for id 0x7f0900b4 (com.example.smartclass:id/recentRecordStatisticsViewPager) for fragment RecentOverallStudentStatusRankingsFragment{8a0f94c #2 id=0x7f0900b4 android:switcher:2131296436:0}
2019-02-25 14:50:10.292 12007-12007/com.example.smartclass E/FragmentManager: Activity state:
2019-02-25 14:50:10.350 12007-12007/com.example.smartclass E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.smartclass, PID: 12007
java.lang.IllegalArgumentException: No view found for id 0x7f0900b4 (com.example.smartclass:id/recentRecordStatisticsViewPager) for fragment RecentOverallStudentStatusRankingsFragment{8a0f94c #2 id=0x7f0900b4 android:switcher:2131296436:0}
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1454)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3269)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3229)
at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:2466)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1483)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3269)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3229)
at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:2466)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1483)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:797)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:2243)
at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:654)
at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:146)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1244)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:669)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:631)
at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:612)
at android.support.design.widget.TabLayout$ViewPagerOnTabSelectedListener.onTabSelected(TabLayout.java:2831)
at android.support.design.widget.TabLayout.dispatchTabSelected(TabLayout.java:1608)
at android.support.design.widget.TabLayout.selectTab(TabLayout.java:1601)
at android.support.design.widget.TabLayout.selectTab(TabLayout.java:1569)
at android.support.design.widget.TabLayout$Tab.select(TabLayout.java:1874)
at android.support.design.widget.TabLayout$TabView.performClick(TabLayout.java:2059)
at android.view.View$PerformClick.run(View.java:22695)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:185)
at android.app.ActivityThread.main(ActivityThread.java:6615)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:916)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:806)
通过分析报错,我们可以看到崩溃的原因是
No view found for id 0x7f0900b4 (com.example.smartclass:id/recentRecordStatisticsViewPager) for fragment RecentOverallStudentStatusRankingsFragment{8a0f94c #2 id=0x7f0900b4 android:switcher:2131296436:0}
也就是说,在 fragment 中查找不到 id 为 recentRecordStatisticsViewPager 的组件。
但是为什么会出现这种情况呢,我进行了一下软件的整体结构分析,这个 APP 打开后即用 TabLayout + ViewPager 实现了一个底部导航栏,然后在近期记录这个子页面中,又再次使用了 TabLayout + ViewPager 实现了一个顶部导航栏,紧接着在班级这个子页面下,使用 ExpandableList 实现了一个可伸缩的列表,之后在列表的子项目中又再次使用 TabLayout + ViewPager 实现了两个小的分标签页面。
从整体的结构入手,排查代码同时上网查找资料,网上提示的最多的一种是在 Fragment 中嵌套的 Fragment 如果想要获取 FragmentManager 需要使用 fragment.getChildFragmentManager() 而不是 fragment.getFragmentManager(),但是这种原因我提前已经考虑过了,所以问题不在这里。
第二个可能性是出在 ViewPager 上面,进行资料的查找后,发现 ViewPager 工作机制是这样的:
在使用 ViewPager 与 Fragment 的时候,ViewPager 会自动缓存一页内的数据,如下图:
所以当我们当前处在 页面2 的时候,页面1 和 页面3 的 View 实际上已经创建好了,所以在我们拖动的时候是可以看见他们的界面的。但是当我们的页面处在 页面1 的时候,页面3 实际上就已经销毁了,直到跳转到 页面2 的时候,页面3 才会创建 View 。也就是说,每次他都是只缓存相邻的一个页面的,而当前页面的相邻的第二个开始的页面都会被销毁。
这样我们也就找到了问题所在,即当我们从 近期记录 跳转到 个人中心 的页面后,近期记录 的页面其实就已经被销毁了,所以才会发生 “ 在 fragment 中查找不到 id 为 recentRecordStatisticsViewPager 的组件 ” 这样的问题。
找到了问题所在,想要解决问题就很简单了,只需要将 ViewPager 的缓存页面数增加到两页,那么当我们访问 个人中心 页面的时候 近期记录 页面就不会被销毁了,这样当我们再点击回去的时候,就可以正常的进行访问了,解决的代码如下:
ViewPager.setOffscreenPageLimit(2);
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!