android fragmentstatepageradapter框架,安卓爬坑指南之FragmentStatePagerAdapter

一次开发中,用到了viewpager嵌套viewpager,结果就踩到了这么一个坑。

先上图:

aeb7da22c8f9

image.png

图片中显示的界面布局和遇到的问题是这样的:首页发现版块是一个fragment,这个fragment中放了一个viewpager,这个viewpager有三页,其中最后一页对应的fragment又放了一个viewpager,内层的viewpager有两页。进入发现时,从外层viewpager第一页切到第三页,加载内层viewpager第一页的数据,然后切回外层viewpager第一页,当再次切到外层viewpager第三页时,出现了神奇的一幕,之前加载的内层viewpager第一页界面展示的数据神奇的不见了。

好吧,我自己都被说晕了,反正大概就是这么一个情况。

首先我外层viewpager和内层viewpager用的adapter都是继承自FragmentStatePagerAdapter,viewpager的默认缓存页为1,因此首先我可以确认的是,外层viewpager在第一页和第三页切换显示时,fragment会有销毁和创建。当外层viewpager从第三页切回第一页时,此时第三页的fragment被释放,正常的逻辑是第三页fragment内层的viewpager包含的两个fragment也是被释放的,当然,这也只是理论上的。为了验证自己的猜想,我在对应fragment onDestory方法中写一条Log,下面是控制台输出的截图:

aeb7da22c8f9

logcat.png

Log的显示验证了我的猜想,所以问题到底出在哪里呢?我们继续写Log,这次我们把外层viewpager第三页的fragment和内层viewpager第一页fragment内存地址输出来:

aeb7da22c8f9

first.png

aeb7da22c8f9

second.png

比较来回切换两次的控制台信息我们可以看到,外层viewpager第三页的fragment内存地址没有变化,因为viewpager数据源没有变,fragment只是重走了生命周期,而fragment重新走生命周期时,内层viewpager对应的数据源是重新创建的,控制台打印的内层viewpager第一页fragment内存地址不一样正好验证了这是两个fragment,既然两个对象都不一样,fragment重新创建,数据重新加载,就不存在界面数据不显示的问题,可是结果并不是我想的那样,这就尴尬了!

冷静的思考了一下,既然fragment是重新创建的,会不会出现adapter返回的fragment不一致呢?继续写Log:

aeb7da22c8f9

first1.png

aeb7da22c8f9

second1.png

看完Log我惊呆了,第二次重新创建了fragment,但是adapter竟然没有返回fragment,wtf???那adapter没有返回fragment,界面显示的fragment哪里来的呢?第一反应想的是不是适配器有缓存,切回来时直接走的缓存,查阅FragmentStatePagerAdapter源码,果不其然,被我找到了!源码如下:

@Override

public 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 i=0; i

Fragment 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;

}

@Override

public 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 i=0; i

mSavedState.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看看这两个方法到底有没有走:

aeb7da22c8f9

first2.png

aeb7da22c8f9

second2.png

果然,FragmentStatePagerAdapter在外层viewpager第三页fragment销毁时保存了状态,再次切回来时,虽然fragment重走了生命周期,但是由于FragmentStatePagerAdapterde直接取的缓存,销毁时只保存了fragment的状态,切回时缓存的fragment状态恢复,但是数据源已经释放,从而导致界面数据不显示。

至此,我们终于找到了bug罪魁祸首!所以这个问题的解决方案是去掉FragmentStatePagerAdapterde 缓存,具体代码如下:

public class BaseFragmentPageAdapter extends FragmentStatePagerAdapter {

public BaseFragmentPageAdapter(FragmentManager fm) {

super(fm);

}

@Override

public Fragment getItem(int position) {

return null;

}

@Override

public int getCount() {

return 0;

}

@Override

public Parcelable saveState() {

return null;

}

@Override

public void restoreState(Parcelable state, ClassLoader loader) {

}

}

讲了这么多,不知道各位有没有看懂!😂😂😂

如果大家有遇到类似的问题,希望这篇博客对你们有帮助,最后,希望大家多多鼓励,我会继续努力把博客写的更好!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/301511.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

每日一笑 | 一个男人逐渐变心的过程

全世界只有3.14 % 的人关注了数据与算法之美&#xff08;图片来源于网络&#xff0c;侵权删&#xff09;

html 表格 左侧表头,左侧是表头的JS表格控件(自写,网上没有的)

今天&#xff0c;项目中要用到该表格&#xff0c;找了一遍&#xff0c;发现没有合适的&#xff0c;于是自己动手丰衣足食。最终呈现效果如上图&#xff0c;1、左侧是表头的表格数据展现&#xff0c;2、支持多行&#xff0c;多表头3、固定表头的功能4、能够支持标题5、获取表格中…

一个人的夜晚,让这些公众号来温暖你。

“外表的美只能取悦于人的眼睛&#xff0c;而内在的美却能感染人的灵魂”。阅读的内容决定了你的视野&#xff0c;转发的内容展现了你的底蕴。这些优质内容&#xff0c;你值得拥有&#xff0c;看下去你就知道。【关注方式&#xff1a;长按二维码&#xff0c;选择“识别图中二维…

grub参数介绍。

为什么80%的码农都做不了架构师&#xff1f;>>> grub的配置文件在/boot/grub/grub.conf。/etc/grub.conf和/boot/grub/menu.lst都是指向这个文件的软连接。 grub启动时&#xff0c;会寻找menu.lst文件&#xff0c;如果找不到&#xff0c;则进入grub>交互界面。…

又一次Task.Wait引起的教训

最近一用户在使用BeetleX.HttpClient组件并发访问延时比较高的https服务时引起了卡死现像。由于组件更多使用场景是内部服务和非https&#xff0c;一直没有这情况出现;但用户提供测试场景下这情况必现&#xff0c;所以翻查了一些相关代码。protected virtual void OnSslAuthent…

html盒模型向上浮动,HTML5盒模型、浮动和定位

在此之前我们先了解一下块级元素和行内元素的区别一、块级元素1、总是从新的一行开始2、高度、宽度都是可控的3、宽度没有设置时&#xff0c;默认为100%4、块级元素中可以包含块级元素和行内元素二、行内元素1、和其他元素都在一行2、高度、宽度以及内边距都是不可控的3、宽高就…

关于一个js栈溢出的异常

快一年没写web端的东西了&#xff0c;今天写了点东西。唉&#xff0c;快忘了&#xff0c;不过还好&#xff0c;基本的开发技能还是练出来了&#xff0c;这东西不能忘。 另外在这里贴点代码&#xff0c;预防以后会出现类似的情况。 javascript代码 //列表数据var appText new A…

科学中有故事,故事中有科学

▲数据汪特别推荐点击上图进入玩酷屋小木用真金白银来给大家送礼物啦&#xff0c;特别感谢这些年一直以来大家对我们的支持&#xff0c;才让我们越做越好。&#xff08;点我参与送礼活动&#xff09;孩子缺什么&#xff1f;不应该只是知识是独立思考意识、逻辑思维能力基于科学…

[译]WPF开源控件扩展库ControlzEx

原文链接&#xff1a;https://github.com/ControlzEx/ControlzEx翻译&#xff1a;沙漠尽头的狼&#xff08;谷歌及百度提供翻译支持&#xff09;Shared Controlz for WPF支持 .NET Framework&#xff08;4.5.2、4.6.2 及更高版本&#xff09;、.NET Core (3.1) 和 .NET 5&#…

html图片分开,webpack单独分离打包css,css里引用的图片路径错误,怎么解决?

现在我的这个项目是将css和js单独打包出来&#xff0c;打包后的目录结构和打包前一致。打包前&#xff1a;从这张图可以看到&#xff0c;如果是css文件夹根目录下的css文件引用images文件夹下的图片应该使用../就可以了&#xff0c;如果是css下某一个文件夹下面的css引用图片的…

每日一笑 | 程序员千万不能轻易去网吧!

全世界只有3.14 % 的人关注了数据与算法之美&#xff08;图片来源于网络&#xff0c;侵权删&#xff09;

.Net Core with 微服务 - Consul 注册中心

上一次我们介绍了 Ocelot 网关的基本用法。这次我们开始介绍服务注册发现组件 Consul 的简单使用方法。服务注册发现首先先让我们回顾下服务注册发现的概念。在实施微服务之后&#xff0c;我们的调用都变成了服务间的调用。服务间调用需要知道IP、端口等信息。再没有微服务之前…

指定特定的内容为首页

2019独角兽企业重金招聘Python工程师标准>>> 默认的情况下&#xff1a;drupal7是将新发表的文件都显示在首页中。 通过下面的方法&#xff0c;指定特定的内容为首页&#xff1a; 管理--》配置--》系统--》站点信息--》默认首页&#xff0c;将相应的内容地址写入&a…

Python到底是有什么魅力,让程序猿为它折腰?

在大数据时代&#xff0c;信息更新非常快速&#xff0c;计算机语言也犹如雨后春笋般被我们所熟知。C语言、C、Java等可谓是各领风骚、独占鳌头&#xff0c;而Python则是一门近几年崛起很快也很火的编程语言。虽说编程语言难分好坏&#xff0c;各有千秋。但Python到底有什么魔力…

jenkins代理设置

2019独角兽企业重金招聘Python工程师标准>>> 抱怨&#xff1a;对于像我这样苦逼的用户&#xff0c;机器在内网&#xff0c;干啥都要“偷偷”通过代理。 言归正传&#xff0c;jenkins\hudson默认并没有提供proxy设置&#xff0c;nexus仓库倒是提供里proxy设置。jenk…

.NET 6 Preview5+VS2022实战千万并发秒杀项目,帅爆了(附源码)

Microsoft 宣布了Visual Studio 2022 的第一个预览版&#xff0c;并且同时也发布了.NET 6 Preview 5。具有里程碑意义的Visual Studio 2022 Preview 1正式发布&#xff0c;重点是64位&#xff0c;而没有增加新功能&#xff0c;并且同时也发布了.NET 6 Preview 5。下面的内容来自…

你们要的印度布线,这是一种极端的牛X

全世界只有3.14 % 的人关注了数据与算法之美前天&#xff0c;数据汪分享了一篇文章「德国布线牛到不行&#xff1f;今天带你看看中国的&#xff01;」&#xff0c;一个中国的布线&#xff0c;小伙伴们表示非常过瘾&#xff0c;强迫症的最爱。不过数据汪也收到不少粉丝留言说&am…

MIPS衰落 LoongArch崛起

不久前&#xff0c;龙芯发布了自主指令集LoongArch和基于LoongArch设计的3A5000&#xff0c;与MIPS彻底分道扬镳。从龙芯最初基于MIPS添加指令&#xff0c;到发展出基于MIPS的LoongISA&#xff0c;再到最新的LoongArch&#xff0c;龙芯的目的是非常明确的&#xff0c;也是显而易…

html答题赚钱源码,WTS在线答题系统 v1.0.0

WTS在线答题系统为在线答题系统(在线考试)&#xff0c;支持在线考试、在线练习等功能... 支持题型&#xff1a;单选题、多选题、填空题、问答题、判断题、附件题、材料题、视频题、音频题支持答题类型&#xff1a;手工配置 试卷答题、随机抽题练习社交功能&#xff1a;试题收藏…

连锁反应装置积木好玩到尖叫!

▲数据汪特别推荐点击上图进入玩酷屋小木用真金白银来给大家送礼物啦&#xff0c;特别感谢这些年一直以来大家对我们的支持&#xff0c;才让我们越做越好。&#xff08;点我参与送礼活动&#xff09;之前推荐的“小小机械师”成了孩子最受欢迎的玩具&#xff0c;玩了的孩子几乎…