Android开发 如何最优的在Activity里释放资源
前言
当前你已经入门Android开发,开始关注深入的问题,你就会碰到一个Android开发阶段经常碰到的问题,那就是内存泄漏. 其实大多数Android的内存泄漏都是因为activity里的资源释放不正确导致,activity与单例或者接口互相持有无法释放.这篇博客就来讲解如何在Android里最优的释放资源.
请注意,此篇博客只是一个思维参考,请不要将全部activity的资源释放都套用这个方式,其实释放资源与初始化资源最好的方式是深刻理解Activity的生命周期,来决定何时初始化资源何时释放资源!
错误释放资源的一些例子
在看正面例子之前,我们看看反面例子,了解为什么经常莫名其妙的内存泄露
在Activity的onDestroy()的生命周期里释放资源
在下面的onDestroy()方法里我们有一个叫mHttpList的资源要释放,我们都知道activity的生命周期的最后是onDestroy方法,那么为什么在onDestroy()里释放资源会有问题呢?
问题出在onDestroy()生命周期并不是立即执行的.Activity退出前台后先是进入栈里的.是否执行onDestroy()是交给系统决定的,一般情况下系统的确会及时的运行onDestroy()方法销毁activity,但是在一些Activity跳转频繁的情况下可能系统并不会马上运行onDestroy()方法.这个时候问题就出现了你认为应该结束的资源并没有马上结束可能导致一些回调报错或者内存泄露.
@Override
protected void onDestroy() {
super.onDestroy();
if (mHttpList != null){
mHttpList.release();
mHttpList = null;
} }
在Activity的finish()方法里释放资源
同上环境,那么finish方法里释放资源有那些问题呢?
重写的finish()是一个释放资源的好地方,在按返回键(或者你自己主动调用onBackPressed()方法)和主动调用finish()方法时,重写的finish()都是会运行的.但是在这个方法在有一种情况下是不运行的,就是在后台太久后的自动清理或者其他Activity的启动模式是android:launchMode="singleTask" 在其他activity的singleTask下会自动清理它栈前的所以Activity,在这种情况下如果你的activity要被清理掉finish()方法是不会运行的.这样你的资源就没有被释放了.
@Override
public void finish() {
super.finish();
if (mHttpList != null){
mHttpList.release();
mHttpList = null;
}
}
在Activity的onPause()和onStop()里释放资源
在onPause()和onStop()我们都知道activity后台的时候会调用这2个生命周期先onPause() 然后在 onStop(),如果是Dialog模式的Activity弹出只会进入onPause(). 他们的问题是什么呢?
问题是如果在操作太快的操作前后台,就会导致我们的资源需要频繁的在onRestart()或者onResume() 重新初始化或者注册.这是较好的一种释放资源的方式一般情况下是推荐这种的,但是快速频繁的操作初始化与释放是最容易出现内存泄漏的...特别是初始化如果是耗时的...
@Override
protected void onPause() {
super.onPause();
Log.e(TAG, "onPause: ");
} @Override
protected void onStop() {
super.onStop();
Log.e(TAG, "onStop: ");
}
Activity里释放资源的方式一
onPause()或者onStop()结合onDestroy(),调用isFinishing()在方法判断后释放资源,如下代码:
private boolean mIsRelease = false; /**
* 释放资源
*/
private void release(){
if (mIsRelease){
return;
}
if (isFinishing()) {
if (mHttpList != null) {
mHttpList.release();
mHttpList = null;
}
}
mIsRelease = true;
} @Override
protected void onPause() {
super.onPause();
//结合实际情况也可以在onPause方法里 释放资源,但是这里释放资源有一个问题你需要知道并且避免:
//在onPause生命周期执行的瞬间,activity其实是还在前台的,所以有概率出现资源已经被释放,但是activity里的View是还有被点击的机会导致空指针报错(特别是在跑monkey的时候,容易出现这种报错)
} @Override
protected void onStop() {
super.onStop();
release(); } @Override
protected void onDestroy() {
super.onDestroy();
release();
}
注意添加判空或者也可以在方法里套一个全局布尔值来判断是否释放过资源,防止重复释放资源... 这里为什么onDestroy()还要运行一次?下面会说明原因.
首先讲讲isFinishing()的作用就是判断这个activity是不是需要被销毁,还是只是进入后台.我验证过以下情况:
1.在主动调用finish()方法的情况下,isFinishing() 返回的是true
2.在主动调用onBackPressed()方法或者按返回键的情况下, isFinishing() 返回的是true
3.如果只是因为进入到其他Activity而退到后台, isFinishing() 返回的是false
注意点:
1.完全依靠isFinishing()来决定释放资源并不完美,还有一种情况可以跳过清理的,那就是SingleTask模式下这个Activity要被销毁,但是后台因为入栈(入深栈最少在第三层的那种情况)已经触发过onPause或者onStop,所以SingleTask的清理就跳过了isFinishing()判断,直接走到了onDestroy().所以,我们需要在onDestroy()再次兜底,保证不会因为SingleTask的原因没有释放资源.
2.在onPause里释放资源需要慎重,在onPause生命周期执行的瞬间,activity其实是还在前台的,所以有概率出现资源已经被释放,但是activity里的View是还有被点击的机会导致空指针报错(特别是在跑monkey的时候,容易出现这种报错)。
最后总结,以上这种释放资源的组合,目的是在Activity真的要被销毁的时候能尽快的释放资源,又可以防止Activity只是在后台时需要重复注册资源,最后依靠onDestroy()兜底保证资源不会因为SingleTask原因没有释放
End
Android开发 如何最优的在Activity里释放资源的更多相关文章
- Android开发艺术探索读书笔记——01 Activity的生命周期
http://www.cnblogs.com/csonezp/p/5121142.html 新买了一本书,<Android开发艺术探索>.这本书算是一本进阶书籍,适合有一定安卓开发基础,做 ...
- android开发中如何结束所有的activity
每一个activity都有自己的生命周期,被打开了最终就要被关闭. 四种结束当前的activity方法 //关闭当前activity方法一 finish(); //关闭当前界面方法二 android. ...
- 【转】android开发中如何结束所有的activity
原文网址:http://java--hhf.iteye.com/blog/1826880 每一个activity都有自己的生命周期,被打开了最终就要被关闭. 四种结束当前的activity方法 //关 ...
- 【Android开发-8】生命周期,Activity中打开另外一个Activity
前言:生命中有很多人陪伴自己走过一生中的某段旅程,仅仅是有些人仅仅是某阶段出现,有些人却陪伴自己非常久.就像小学.中学.高中.大学,那些以前以为会长久拥有的,当经历过天涯各地地忙碌于生活,或如意.或失 ...
- android开发艺术探索学习 之 结合Activity的生命周期了解Activity的LaunchMode
转载请标明出处: http://blog.csdn.net/lxk_1993/article/details/50749728 本文出自:[lxk_1993的博客]: 首先还是先介绍下Activity ...
- Android开发学习之路-Service和Activity的通信
在很多时候,Service都不仅仅需要在后台运行,还需要和Activity进行通信,或者接受Activity的指挥,如何来实现,来看代码. 定义一个服务 // 创建一个服务,然后在onBind()中返 ...
- Android开发艺术探索(一)——Activity的生命周期和启动模式
Activity的生命周期和启动模式 生命周期有? 1.典型情况下的生命周期—>指有用户参与的情况下,Activity所经过的生命周期改变 2.异常情况下的生命周期—>指Activity被 ...
- android开发 一个更优的listView的写法
布局xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:androi ...
- Android开发之利用ViewPager实现在Activity或Fragment中引入别的布局文件实现滑动并进行页面跳转
有些时候经常可以看到其他APP中有一排的图标,可以在一个界面中滑来滑去,并且图标可以进行点击事件进行页面的跳转.这里对这种方法的实现做出总结. 首先看一下图片: 下面这两种图片是在一个Fragment ...
随机推荐
- Ubuntu12.04下删除文件夹内所有的.svn文件
前段时间在公司里遇到一个问题,从svn上下载下来的文件含有.svn文件,如何删除当前目录下的所有.svn文件呢? 一个个手动删除显然不可能,太多了.其实在Ubuntu12.04下延伸至其他所搜的Lin ...
- Centos光盘ISO安装过程再理解
ISO启动时的基本流程 vmlinuz -> 加载initrd.img -> 加载内核基本驱动 -> 挂载光盘至/run/install/repo -> 启动anaconda ...
- element ui设置表格表头高度和每一行的高度
填坑记录:今天用element ui的表格组件做用户信息展示,直接拉取的官网的代码过来,发现表头和每一行都太高了,如下: 因为第一次使用element ui的表格组件,不太清楚会遇到这样的坑,以为能轻 ...
- java oop第15章_Socket网络编程
一. TCP/IP协议(Transmission Control Protocol/Internet Protocol)传输控制协议/Internet协议,是通信领域的基础.核心协议, 其他的协议 ...
- Android基础——框架模式MVC在安卓中的实践
本篇文章包含以下内容: MVC的介绍 MVC的实践 MVC的介绍 MVC (Model View Controller),是模型(model)视图(view)控制器(controller)的缩写,一种 ...
- 2019_8_1python
#函数 #函数是用来重复使用哒 #定义函数套路 ''' 1.首先要会写出裸代码,然后看看哪里是重复需要使用的 2.接下来将需要重复使用的代码转换成参数,带入到函数中 函数格式 def funcName ...
- 2019牛客暑期多校训练营(第六场)Palindrome Mouse 回文树+dfs
题目传送门 题意:给出一个字符串,将字符串中所有的回文子串全部放入一个集合里,去重后.问这个集合里有几对<a,b>,使得a是b的子串. 思路:一开始想偏了,以为只要求每个回文串的回文后缀的 ...
- B 树 B+树
拜读了 http://blog.csdn.net/v_july_v/article/details/6530142, 自己总结下: B树的出发点是为了解决磁盘IO慢的问题,尽量再一个磁盘块中提供更 ...
- Spring常见面试题及答案解析
.说一下spring中Bean的作用域 singleton: Spring IoC容器中只会存在一个共享的Bean实例,无论有多少个Bean引用它,始终指向同一对象.Singleton作用域是Spri ...
- 覆盖element ui 的样式
我们可以使用 !important 来覆盖element ui 的样式 首先先在浏览器中找到 我们所要修改的样式 ,然后找到她的 class 重新写他的样式 ,例如 . app { width ...