使用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 系统上错误,导致应用 ...
随机推荐
- SC.Lab3对于Factory的构建过程(from HIT)
Factory设计模式基本就是通过传入指定的参数/或者不传入参数,通过Factory的某个方法(为了避免实例化Factory对象,一般方法为静态static),来获取一个对象.这个是Factory用的 ...
- (3)LoraWAN:链路控制、SF BW CR
三.Introduction on LoRaWAN options 本文件描述了一种用于可为移动的或固定在一个固定位置的电池供电的终端设备而优化的LoRaWAN™网络协议.LORA™是一个由Semte ...
- JavaScript之bind方法实现代码分析
我们来分析一下bind方法的实现代码,下图的bind方法的实现为MDN(开发者社区)中的代码. 由上图可得:bind方法实现了两个功能:绑定this和科里化.
- 修改Xshell字体大小和颜色
博客专区 > XManager的博客 > 博客详情 修改Xshell字体大小和颜色 XManager 发表于7个月前 分享到: 一键分享 QQ空间 微信 腾讯微博 新浪微博 QQ好友 有道 ...
- IdentityServer4专题之六:Resource Owner Password Credentials
实现代码: (1)IdentityServer4授权服务器代码: public static class Config { public static IEnumerable<Identity ...
- CBC加密原理及攻击
原理基于分组加密加密过程 Plaintext:明文,待加密的数据.IV:用于随机化加密的比特块,保证即使对相同明文多次加密,也可以得到不同的密文,初始向量,用来与第一块的明文异或运算.Key:被一些如 ...
- DEDE后台升级后不显示编辑器
dede5.7不显示编辑器不能编辑文章的解决办法:进入系统后台系统配置-系统基本参数-核心设置将fck换成ckeditor保存,当然需要fck编辑器也可以到dede官网下载.dede5.7不显示编辑器 ...
- node批量修改文件名称
let fs = require('fs');//引用文件系统模块 let PATH = `./app_zijietiaodong/`;//当前文件夹 let ext = { readFileList ...
- python 输入年月日,返回当天是星期几
引入内置模块calendar,输入年.月.日,根据weekday(year,month,day)的返回值,输出该日期是星期几.函数weekday()返回0-6分别对应星期一至星期日 import ca ...
- Metasploit学习笔记——网络服务渗透攻击
1.内存攻防技术 1.1缓冲区溢出漏洞机理 1.2栈溢出利用机理 1.3缓冲区溢出利用的限制条件 2.网络服务渗透攻击面 3. Windows服务渗透攻击实战案例——MS08-067安全漏洞 示例代码 ...