使用FragmentStatePagerAdapter时发现的内存泄露问题
这篇文章想说的并非是由于使用 FragmentStatePagerAdapter 而导致的内存泄漏,内存泄漏的真正原因和 FragmentStaePagerAdapter 并无直接关联,但是使用 FragemntStatePagerAdapter 能让你更加直观的发现内存泄漏。
我先说说我之前遇到的问题。我们都知道,当使用 FragmentSataePagerAdapter 的时候,超出缓存范围的 Fragment 会被 FragmentManager 给 remove 掉,也就是会被销毁实例,所以FragmentSatatePagerAdapter 很适合用来处理多 Fragment 页面的状况。但我遇到的情况是,当我的 Fragment 超出缓存范围时,确实被销毁了,但是它所持有的内存却并未得到释放,也就是说它内部的数据等等并未销毁和回收。如果是页面很多的情况下,很容易就会造成程序的卡顿甚至 OOM。
一般来说,造成内存泄漏的最大可能就是某处持有该对象的引用,导致该对象无法释放内存。经排查,我在使用 ViewPager 时,创建了一个 Fragment 的 List ,用来管理所有要添加到 ViewPager 中的 Fragment ,这里的 List 可能强引用了所有的Fragment,所以造成了内存泄漏 。代码如下:
private List<Fragment> fragmentList = new ArrayList<>(); //创建List,用来管理所有要添加到ViewPager的Fragment
//添加Fragment
private void setUpFragments() {
fragmentList.clear();
fragmentList.add(new SampleListFragment());
fragmentList.add(new SamplePagerFragment());
fragmentList.add(new BlankFragment());
} viewPager.setAdapter(new FragmentStatePagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return fragmentList.get(position); //从Fragment队列中得到Fragment并加入到ViewPager中
} @Override
public int getCount() {
return fragmentNames.size();
}
});
那么如何来验证是不是这里的原因造成内存泄漏呢?想要证明,首先就不能够在使用 List 来管理 Fragment对象了。ViewPager最麻烦的是你不能自己使用 FragmentManager 的transaction 来添加 Fragment ,因为这些操作是在 ViewPager 的内部去完成的。最后我考虑使用 List 来管理Fragment的CLASS 类,然后再通过反射的方式,创建出 Fragment 对象。这样 Fragment 对象就不会被 List 持有引用了。具体代码如下:
private List<Class> fragmentNames; //创建List来管理 Fragment的 Class //添加Fragment的Class到List中
private void setUpFragments() {
if(fragmentNames == null){
fragmentNames = new ArrayList<>();
}
fragmentNames.clear();
fragmentNames.add(SampleListFragment.class);
fragmentNames.add(SampleListFragment.class);
fragmentNames.add(SampleListFragment.class);
fragmentNames.add(SampleListFragment.class);
} viewPager.setAdapter(new FragmentStatePagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
try {
return (Fragment) fragmentNames.get(position).newInstance(); //反射加载Fragment
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
} @Override
public int getCount() {
return fragmentNames.size();
}
});
如果不会反射的同学可以看一下我前面写的介绍反射的简单使用的文章。
现在再来检查程序的内存状况,你就会发现内存能够正确的被释放,内存泄漏的问题也就解决了。
其实我以前使用 ViewPager + Fragment 的时候也并没有注意到内存泄漏的问题,直到使用了FragmentStatePagerAdapter 时才发现原来的写法可能会造成内存泄漏。当然,程序中还会有很多地方稍不注意就会导致内存泄漏的问题,我们平时写代码时应该多多考虑内存泄漏的问题,并对此进行优化。
使用FragmentStatePagerAdapter时发现的内存泄露问题的更多相关文章
- 使用ViwePager显示图片时如何防止内存泄露。
内存泄露的检测. 1. 在Android Studio中运行你的应用,然后切换到输出窗口的Android tab. 2. 尽情的玩耍你的应用,最好各个功能都用到,如果是Viewpager,则多滑动一些 ...
- Delphi结构中使用String时遇到的内存泄露问题(没有利用String的引用计数自动销毁字符串的功能)
先定义一个结构: TUserInfo = record UserID: Integer; // 用户编号 UserName: string; // 用户名end; 然后编写如下代码: proced ...
- javascript js 内存泄露工具使用
javascript内存泄露工具使用 原文:http://lanhy2000.blog.163.com/blog/static/43678608201121472644851/ 2011-03-14 ...
- FastMM内存泄露
转自:http://www.2ccc.com/article.asp?articleid=4879FastMM是非常优秀的内存管理器,但是从FastMM4Options.inc中找到合适自已程序的选项 ...
- 【翻译】JavaScript内存泄露
原文地址:http://javascript.info/tutorial/memory-leaks#tools 我们在进行JavaScript开发时,很少会考虑内存的管理.JavaScript中变量的 ...
- Visual Studio内存泄露检測工具
使用简单介绍 在敲代码的过程中.难免会遇到内存泄露的时候.这个时候假设手工查找内存泄露,不说方法没有通用的,就是真的要自己手工查找也是非常耗时间和精力的.诚然.我们能够借助一些工具,并且我们还 ...
- LeakCanary: 让内存泄露无所遁形
LeakCanary: 让内存泄露无所遁形 09 May 2015 本文为LeakCanary: Detect all memory leaks!的翻译.原文在: https://corner.squ ...
- go内存泄露case
用go写了一个守护进程程序:用于检測redis的存活状态并将结果写到zookeeper中,部署到redis机器上.对于每一个redis实例会有一个goroutine每隔固定时间去检測其状态,由主gor ...
- dotnet 6 在 Win7 系统证书链错误导致 HttpWebRequest 内存泄露
本文记录我将应用迁移到 dotnet 6 之后,在 Win7 系统上,因为使用 HttpWebRequest 访问一个本地服务,此本地服务开启 https 且证书链在此 Win7 系统上错误,导致应用 ...
随机推荐
- 华为轮值CEO,富士康却坚持独裁,二者究竟有什么不一样?
谈到深圳龙华的大企业,人们会很自然地想到华为和富士康,两家公司毗邻,有两个门仅仅隔着一条马路,都是世界500强,对国家,对社区的经济发展有着重要贡献,员工压力最大的时候,也都出现过自杀的情况,一个讲究 ...
- 6专题总结-动态规划dynamic programming
专题6--动态规划 1.动态规划基础知识 什么情况下可能是动态规划?满足下面三个条件之一:1. Maximum/Minimum -- 最大最小,最长,最短:写程序一般有max/min.2. Yes/N ...
- LATTICE 编程烧录器HW-USBN-2B使用说明
HW-USBN-2B说明文档 1. 引脚定义 编程引脚 名称 编程设备引脚类型 描述 VCC 编程电压 输入 连接VCC到目标设备,典型的ICC=10Ma.板子设计必须考虑VCC的电流供应 ...
- 常见加密解密 -- pycryptodomex库
安装 windows pip install pycryptodomex ubuntu pip install pycryptodome 加密方式 单向加密:MD5 只能对数据进行加密,而不能解密 对 ...
- 三 保存客户&分页查询&Spring解决延迟加载问题
保存客户 Struts2通过模型驱动拿到封装对象,调用业务层将对象传递到持久层,持久层调用Hibernate模版将对象持久化到数据库. 持久层代码实现: 分页查询: 创建PageBean实体类,里面有 ...
- XtraReport1添加参数
解决了在report有个BeforePrint事件这里面直接 C# code ? 1 string year = this.Parameters["year"].Value.T ...
- springboot自定义属性文件与bean映射注入属性值
主要有几点: 一.导入依赖 springboot的包和: <dependency> <groupId>org.springframework.boot</groupId& ...
- xilinx FPGA课程学习总结
一时冲动,跑步进入了FPGA的大门,尤老师是教练,我之前一直做嵌入式软件,数字电路也是十年前大学课堂学过,早已经还给老师了.FPGA对于我来说完全是小白,所以.老师的课程,对于我来说至关重要!因为见过 ...
- JDK8中的HashMap实现原理及源码分析
大纲 一.什么是Hash?什么是HashMap? 二.HashMap的内部实现机制 1.HashMap基本元素 ①DEFAULT_INITIAL_CAPACITY&MAXIMUM_CAPACI ...
- 3 JVM配置参数