Android之Activity结束(finish())之后没有释放内存问题的解决方法
2016-10-10 18:04
633 查看
先来看一个奇怪的问题:
玩android细心一点的就会发现,当打开一个app,点击菜单上的任意一个页面,退回主菜单,看一下ddms,这时的heap used大约在3.5m左右。这时候如果再点击一个页面,退回来,再点击同一个,再退回来,然后无数次(理论上的,呵呵,10次即OK)。
理论上,这个页面所处的activity被销毁,与之相关所有的内存被GC,内存还会在3.5m。
结果是,仅仅10次重复打开关闭同一个activity,内存使用变成5.2m了!而且这多出来的1.7m怎么也去不掉!狂点cause gc? 不理你!我被抛弃了!
痛苦的思索之后,冷静下来,从java的GC机制开始分析。。。。。
我们说GC(Garbage Collection)的真正目的是什么?显而易见。回收没有被其他对象引用到的对象,或者说是引用数为0的对象。
1、释放new出来的对象或者比如findViewById()、 getResourceById()的对象变量
activity在创建界面的时候,由setContentView创建一个主view(即绘制整个界面的父view),由于在finish的时候,这个view还持有activity的引用,因此activity无法被回收,造成内存泄漏。 解决方案显而易见:
public void onDestory(){
textView1 = null;
dataList = null;
......
//etc.
super.onDestory();
}
不出所料,测试结果,反复打开关闭一个页面消耗了1.3m的内存,比之前1.7m的情况好了30%左右。可是,这依然没有满足需求。那么,还有什么地方能提高内存的回收率呢??findViewById的定义:
Finds a view that was identified by the id attribute from the XML that was processed in onCreate(Bundle).
很明显,findViewById返回在onCreate已经创建了的view,并且指定的ID与通过setContentView中指定的xml文件匹配。那么,前面所说的onDestory()里面的置null 方法的作用就很有限了。
2、设置setContentView(R.layout.view_null)
先看看setContentView的定义:
Set the activity content from a layout resource. The resource will be inflated, adding all top-level views to the activity.
不难理解,inflate就是建立一个新android.view.View对象,activity也是通过setContentView并传入一个xml来构建整个activity的view对象以及子对象的!就是说,在onCreate的setContentview 里,有一个contentview = viewInflater.Inflate();或者类似的东东。
所以,我们应该在ondestory把由setContentview创建的contentview置为null,就一劳永逸了。但是不能在ondestory把contentview = null; 因为是父类的私有字段!很多人应该也能感觉到,那就是setContentview(null)!然而,编译报错,NullPointerException。
于是写了一个空的viewxml,命名view_null。编译成功,运行正常。结果是,10个打开关闭一共消耗了0.6M的内存。
3、回收控件的background、src等资源
android中对于控件的background,src等资源不会随activity.finish()而消亡的,要通过如下方法来置空资源
假设控件名为myView
1. 通过控件得到其资源 BitmapDrawable bd = (BitmapDrawable)fl.getBackground();
2. 重新设置控件背景为空 myView.setBackgroundResource(0);
3. 设置callback为空 bd.setCallback(null);
4. 回收资源 bd.getBitmap().recycle();
5. 置空控件对象 myView = null;
玩android细心一点的就会发现,当打开一个app,点击菜单上的任意一个页面,退回主菜单,看一下ddms,这时的heap used大约在3.5m左右。这时候如果再点击一个页面,退回来,再点击同一个,再退回来,然后无数次(理论上的,呵呵,10次即OK)。
理论上,这个页面所处的activity被销毁,与之相关所有的内存被GC,内存还会在3.5m。
结果是,仅仅10次重复打开关闭同一个activity,内存使用变成5.2m了!而且这多出来的1.7m怎么也去不掉!狂点cause gc? 不理你!我被抛弃了!
痛苦的思索之后,冷静下来,从java的GC机制开始分析。。。。。
我们说GC(Garbage Collection)的真正目的是什么?显而易见。回收没有被其他对象引用到的对象,或者说是引用数为0的对象。
1、释放new出来的对象或者比如findViewById()、 getResourceById()的对象变量
activity在创建界面的时候,由setContentView创建一个主view(即绘制整个界面的父view),由于在finish的时候,这个view还持有activity的引用,因此activity无法被回收,造成内存泄漏。 解决方案显而易见:
public void onDestory(){
textView1 = null;
dataList = null;
......
//etc.
super.onDestory();
}
不出所料,测试结果,反复打开关闭一个页面消耗了1.3m的内存,比之前1.7m的情况好了30%左右。可是,这依然没有满足需求。那么,还有什么地方能提高内存的回收率呢??findViewById的定义:
Finds a view that was identified by the id attribute from the XML that was processed in onCreate(Bundle).
很明显,findViewById返回在onCreate已经创建了的view,并且指定的ID与通过setContentView中指定的xml文件匹配。那么,前面所说的onDestory()里面的置null 方法的作用就很有限了。
2、设置setContentView(R.layout.view_null)
先看看setContentView的定义:
Set the activity content from a layout resource. The resource will be inflated, adding all top-level views to the activity.
不难理解,inflate就是建立一个新android.view.View对象,activity也是通过setContentView并传入一个xml来构建整个activity的view对象以及子对象的!就是说,在onCreate的setContentview 里,有一个contentview = viewInflater.Inflate();或者类似的东东。
所以,我们应该在ondestory把由setContentview创建的contentview置为null,就一劳永逸了。但是不能在ondestory把contentview = null; 因为是父类的私有字段!很多人应该也能感觉到,那就是setContentview(null)!然而,编译报错,NullPointerException。
于是写了一个空的viewxml,命名view_null。编译成功,运行正常。结果是,10个打开关闭一共消耗了0.6M的内存。
3、回收控件的background、src等资源
android中对于控件的background,src等资源不会随activity.finish()而消亡的,要通过如下方法来置空资源
假设控件名为myView
1. 通过控件得到其资源 BitmapDrawable bd = (BitmapDrawable)fl.getBackground();
2. 重新设置控件背景为空 myView.setBackgroundResource(0);
3. 设置callback为空 bd.setCallback(null);
4. 回收资源 bd.getBitmap().recycle();
5. 置空控件对象 myView = null;
相关文章推荐
- Android下Activity结束(finish())之后没有释放内存问题的解决方法初探
- Android下Activity结束(finish())之后没有释放内存问题的解决方法
- Android下Activity结束(finish())之后没有释放内存问题的解决方法初探
- Android下Activity结束(finish())之后没有释放内存问题的解决方法
- Android下Activity结束(finish())之后没有释放内存问题的解决方法
- Activity结束finish()之后没有释放内存
- Android加载图片内存溢出问题解决方法
- IE浏览器IFrame对象内存不释放问题解决方法
- 解决 Android中用里ScrollView 之后 Activity 中的 onTouchEvent 失效问题
- 多方通话的时候遇到图片回收问题---目前没有方法解决 Canvas: trying to use a recycled bitmap android.graphics.Bitmap
- 新创建的android工程里面没有activity问题解决
- Android加载图片内存溢出问题解决方法
- 关于Activity调用Ondestroy()方法之后内存管理器为什么没有释放占用资源
- Android 异步获取网络图片并处理导致内存溢出问题解决方法
- 17-1 函数运用结束之后内存就自动释放了,没有返回a,b的值
- Activity调用Ondestroy()方法之后内存管理器为什么没有释放占用资源
- IE浏览器IFrame对象内存不释放问题解决方法
- 线程没有正常结束产生的内存泄露问题的解决
- android中共享全局数据的方法(static导致的内存泄漏问题,但其实并未解决)
- android开发游记:位图压缩技巧与方法总结,解决加载大图内存占用过大问题