这篇文章想说的并非是由于使用 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时发现的内存泄露问题的更多相关文章

  1. 使用ViwePager显示图片时如何防止内存泄露。

    内存泄露的检测. 1. 在Android Studio中运行你的应用,然后切换到输出窗口的Android tab. 2. 尽情的玩耍你的应用,最好各个功能都用到,如果是Viewpager,则多滑动一些 ...

  2. Delphi结构中使用String时遇到的内存泄露问题(没有利用String的引用计数自动销毁字符串的功能)

    先定义一个结构: TUserInfo = record  UserID: Integer; // 用户编号  UserName: string; // 用户名end; 然后编写如下代码: proced ...

  3. javascript js 内存泄露工具使用

    javascript内存泄露工具使用 原文:http://lanhy2000.blog.163.com/blog/static/43678608201121472644851/ 2011-03-14 ...

  4. FastMM内存泄露

    转自:http://www.2ccc.com/article.asp?articleid=4879FastMM是非常优秀的内存管理器,但是从FastMM4Options.inc中找到合适自已程序的选项 ...

  5. 【翻译】JavaScript内存泄露

    原文地址:http://javascript.info/tutorial/memory-leaks#tools 我们在进行JavaScript开发时,很少会考虑内存的管理.JavaScript中变量的 ...

  6. Visual Studio内存泄露检測工具

    使用简单介绍     在敲代码的过程中.难免会遇到内存泄露的时候.这个时候假设手工查找内存泄露,不说方法没有通用的,就是真的要自己手工查找也是非常耗时间和精力的.诚然.我们能够借助一些工具,并且我们还 ...

  7. LeakCanary: 让内存泄露无所遁形

    LeakCanary: 让内存泄露无所遁形 09 May 2015 本文为LeakCanary: Detect all memory leaks!的翻译.原文在: https://corner.squ ...

  8. go内存泄露case

    用go写了一个守护进程程序:用于检測redis的存活状态并将结果写到zookeeper中,部署到redis机器上.对于每一个redis实例会有一个goroutine每隔固定时间去检測其状态,由主gor ...

  9. dotnet 6 在 Win7 系统证书链错误导致 HttpWebRequest 内存泄露

    本文记录我将应用迁移到 dotnet 6 之后,在 Win7 系统上,因为使用 HttpWebRequest 访问一个本地服务,此本地服务开启 https 且证书链在此 Win7 系统上错误,导致应用 ...

随机推荐

  1. Android之Context和Activity互相转换

    1.context转换为activity Activity activity = (Activity) context; 2.从activity得到context 在activity的方法中用cont ...

  2. Bootstrap入门(一)准备

    Bootstrap入门(一)准备         网页的样式化与布局展示是很多开发者要面对的问题,目前有多的框架和工具包,可以使网页设计的任务变得更加简单.轻松.方便.快捷一些,其中,bootstra ...

  3. 「译」forEach循环中你不知道的3件事

    前言 本文925字,阅读大约需要7分钟. 总括: forEach循环中你不知道的3件事. 原文地址:3 things you didn't know about the forEach loop in ...

  4. 使用JavaScript和Canvas打造真实的雨滴效果

    使用JavaScript和Canvas打造真实的雨滴效果 寸志 · 1 年前 我最近搞了一个有趣的项目——rainyday.js .我认为这个项目并不怎么样,而且,事实上这是我第一次尝试接触一些比弹窗 ...

  5. poj 3617 Best Cow Line 贪心模拟

    Best Cow Line Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 42701   Accepted: 10911 D ...

  6. Python学习笔记之基础篇(-)python介绍与安装

    Python学习笔记之基础篇(-)初识python Python的理念:崇尚优美.清晰.简单,是一个优秀并广泛使用的语言. python的历史: 1989年,为了打发圣诞节假期,作者Guido开始写P ...

  7. python2学习------基础语法3(类、类的继承、类成员函数、防御式编程)

    1.类的定义以及实例化 # 类定义 class p: """ this is a basic class """ basicInfo={&q ...

  8. Activity的生命周期及协同作用

    生命周期 onCreate:创建Activity的实例对象的方法 onStart:启动当前的activity实例的方法 onResume:如果该方法执行,页面的实例和用户即可以交互 onPause:如 ...

  9. PHPstudy2018 后门简单使用

    首先声明,仅为记录使用. 测试用例php-5.4.45 + Apache index.php 使用Firefox 浏览器,可以编辑并且重发http请求 打印出“net user” base64 加密后 ...

  10. openCV 3.4 windows下的配置说明

    链接: https://pan.baidu.com/s/1dkS_G8ZSBD8EnhYeEFZxhQ 密码: xu99 (从官网下的, 但360会提示有毒, 哈哈哈) 运行exe, 解压openCV ...