好网站建设公司的网站,建设宁夏分行互联网站,软件开发外包大概多少钱,seo上海培训一次开发中#xff0c;用到了viewpager嵌套viewpager#xff0c;结果就踩到了这么一个坑。先上图#xff1a;image.png图片中显示的界面布局和遇到的问题是这样的#xff1a;首页发现版块是一个fragment#xff0c;这个fragment中放了一个viewpager#xff0c;这个viewpa…一次开发中用到了viewpager嵌套viewpager结果就踩到了这么一个坑。先上图image.png图片中显示的界面布局和遇到的问题是这样的首页发现版块是一个fragment这个fragment中放了一个viewpager这个viewpager有三页其中最后一页对应的fragment又放了一个viewpager内层的viewpager有两页。进入发现时从外层viewpager第一页切到第三页加载内层viewpager第一页的数据然后切回外层viewpager第一页当再次切到外层viewpager第三页时出现了神奇的一幕之前加载的内层viewpager第一页界面展示的数据神奇的不见了。好吧我自己都被说晕了反正大概就是这么一个情况。首先我外层viewpager和内层viewpager用的adapter都是继承自FragmentStatePagerAdapterviewpager的默认缓存页为1因此首先我可以确认的是外层viewpager在第一页和第三页切换显示时fragment会有销毁和创建。当外层viewpager从第三页切回第一页时此时第三页的fragment被释放正常的逻辑是第三页fragment内层的viewpager包含的两个fragment也是被释放的当然这也只是理论上的。为了验证自己的猜想我在对应fragment onDestory方法中写一条Log下面是控制台输出的截图logcat.pngLog的显示验证了我的猜想所以问题到底出在哪里呢我们继续写Log这次我们把外层viewpager第三页的fragment和内层viewpager第一页fragment内存地址输出来first.pngsecond.png比较来回切换两次的控制台信息我们可以看到外层viewpager第三页的fragment内存地址没有变化因为viewpager数据源没有变fragment只是重走了生命周期而fragment重新走生命周期时内层viewpager对应的数据源是重新创建的控制台打印的内层viewpager第一页fragment内存地址不一样正好验证了这是两个fragment既然两个对象都不一样fragment重新创建数据重新加载就不存在界面数据不显示的问题可是结果并不是我想的那样这就尴尬了冷静的思考了一下既然fragment是重新创建的会不会出现adapter返回的fragment不一致呢继续写Logfirst1.pngsecond1.png看完Log我惊呆了第二次重新创建了fragment但是adapter竟然没有返回fragmentwtf那adapter没有返回fragment界面显示的fragment哪里来的呢第一反应想的是不是适配器有缓存切回来时直接走的缓存查阅FragmentStatePagerAdapter源码果不其然被我找到了源码如下Overridepublic Parcelable saveState() {Bundle state null;if (mSavedState.size() 0) {state new Bundle();Fragment.SavedState[] fss new Fragment.SavedState[mSavedState.size()];mSavedState.toArray(fss);state.putParcelableArray(states, fss);}for (int i0; iFragment f mFragments.get(i);if (f ! null f.isAdded()) {if (state null) {state new Bundle();}String key f i;mFragmentManager.putFragment(state, key, f);}}return state;}Overridepublic void restoreState(Parcelable state, ClassLoader loader) {if (state ! null) {Bundle bundle (Bundle)state;bundle.setClassLoader(loader);Parcelable[] fss bundle.getParcelableArray(states);mSavedState.clear();mFragments.clear();if (fss ! null) {for (int i0; imSavedState.add((Fragment.SavedState)fss[i]);}}Iterable keys bundle.keySet();for (String key: keys) {if (key.startsWith(f)) {int index Integer.parseInt(key.substring(1));Fragment f mFragmentManager.getFragment(bundle, key);if (f ! null) {while (mFragments.size() index) {mFragments.add(null);}f.setMenuVisibility(false);mFragments.set(index, f);} else {Log.w(TAG, Bad fragment at key key);}}}}}当传入FragmentStatePagerAdapter的数据源不为空viewpager在被销毁时FragmentStatePagerAdapter会自动保存数据我们接着写Log看看这两个方法到底有没有走first2.pngsecond2.png果然FragmentStatePagerAdapter在外层viewpager第三页fragment销毁时保存了状态再次切回来时虽然fragment重走了生命周期但是由于FragmentStatePagerAdapterde直接取的缓存销毁时只保存了fragment的状态切回时缓存的fragment状态恢复但是数据源已经释放从而导致界面数据不显示。至此我们终于找到了bug罪魁祸首所以这个问题的解决方案是去掉FragmentStatePagerAdapterde 缓存具体代码如下public class BaseFragmentPageAdapter extends FragmentStatePagerAdapter {public BaseFragmentPageAdapter(FragmentManager fm) {super(fm);}Overridepublic Fragment getItem(int position) {return null;}Overridepublic int getCount() {return 0;}Overridepublic Parcelable saveState() {return null;}Overridepublic void restoreState(Parcelable state, ClassLoader loader) {}}讲了这么多不知道各位有没有看懂如果大家有遇到类似的问题希望这篇博客对你们有帮助最后希望大家多多鼓励我会继续努力把博客写的更好