使用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 系统上错误,导致应用 ...
随机推荐
- SQLSERVER|CDC 日志变更捕获机制
先说一下什么是cdc ,cdc 变更数据捕获(Change Data Capture ,简称 CDC)记录 SQL Server 表的插入.更新和删除活动.SQLServer的操作会写日志,这也是CD ...
- VUE - 路由跳转时设置动画效果
/* 为对应的路由跳转时设置动画效果 */ <transition name="fade"> <router-view /> & ...
- SQL statement ignored
存储过程语句错误,字段或变量名可能拼错,导致存储过程无法执行. 解决办法:仔细检查存储过程里的变量,字段,语句等是否正确.
- Redis——进阶
redis的持久化 redis提供两种备份方式,一种是RDB 一种是AOFRDB默认开启.关闭注释掉所有的save,存储的是redis 具体的值,会压缩存储.AOF配置文件中appendonly ye ...
- 使用Ghidra分析phpStudy后门
一.工具和平台 主要工具: Kali Linux Ghidra 9.0.4 010Editor 9.0.2 样本环境: Windows7 phpStudy 20180211 二 .分析过程 先在 Wi ...
- R Akaike information criterion,AIC,一个越小越好的指标
Akaike information criterion,AIC是什么?一个用来筛选模型的指标.AIC越小模型越好,通常选择AIC最小的模型.第一句话好记,第二句话就呵呵了,小编有时候就会迷惑AIC越 ...
- 困惑我的x++和++x;
刚学习C语言时X++和++X非常不解 目前有了新的领悟 1.X++ int x=0; int z=x++; 此时z?x? 这个问题可以分两步思考 第一步:先把x的值赋予z,此时z=x=0; 第二步:x ...
- 018、Java中除法的是用,解决除法计算精度问题
01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...
- mysql 存储引擎入门
- delphi保存和提取ini文件信息
procedure TLoginForm.FormShow(Sender: TObject);var ini:TIniFile; name:string;begin //实现动态提取数据库的登录用户名 ...