很多人(应该是所有用过DDMS或者是ANDROID自带的任务管理器)玩android细心一点 的就会发现,当打开一个app,进入主页面,跳到登陆画面,登陆之后返回到菜单, 再点击菜单上的任意一个页面,点击了,退回主菜单,看一下ddms,这时的heap used 大约在3.5m左右。
这时候如果再点击一个页面,退回来,再点击同一个,再退回来, 然后无数次(理论上的,呵呵,10次即OKAndroid下Activity结束(finish())之后没有释放内存问题的解决方法初探)。一般来说(除了 极个别的app),退回来就是结束当前activity, 也就是使得activity 的生命周期走到最后的一刻destory,之后理论上这个activity被销毁, 与之相关所有的内存被GC,内存还会在3.5m。
结果是,仅仅10次重复打开关闭同一个activity,内存使用变成5.2m了! 而且这多出来的1.7m怎么也去不掉!狂点cause gc? 不理你!我被抛弃了! 情急之下,我的重要的恋人----java顷刻之间让我感觉那么的陌生,她最 重要,也是和C相比最美丽的地方之一----垃圾回收立即烟消云散,荡然无存。
。。。。。。。 。。。。。。。
痛苦的思索之后,冷静下来,从java的GC机制开始分析。。。。。 
我们说GC(Garbage Collector)的真正目的是什么?显而易见。 回收没有利用价值的被占用的内存。那么怎样的 内存区域不能被使用或者访问了呢?没有被其他对象 引用到的对象,或者说是引用数为0的对象。 
从以上的分析,可以猜想,对象没被释放,因为有 其他对象在引用它。所以,我们把activity结束掉后 必须释放那些在activity中new出来或者是从其他地方 比如findViewById() getResourceById()这种地方获得 的activity字段。 解决方案显而易见:
public void onDestory(){      textView1 = null;      dataList = null;      ......       //etc. super.onDestory();

不出所料,测试结果,反复打开关闭一个页面消耗了1.3m的内存,比 之前1.7m的情况好了30%左右。可是,这依然没有满足需求。
那么,还有什么地方能提高内存的回收率呢??
我们再回到前面提到的GC的性质和功能。如果GC不释放一部分内存,那么这一部分 的内存肯定是还被其他的对象引用。 但是如何去找到关闭了activity而仍然被引用的对象呢? 这里就是问题的关键了。 一般性会写安卓的朋友们都会想起一个方法,就是前面提到的findViewById()
说起这个方法,我们一般都想到把findViewById()的对象赋给自定义Activity的类字段。 比如说,textView = findViewById(R.id.tv1); 在ondestory里把 textView = null加上,在destory的时候activity将不再引用textView 所指的对象实体了。然而,findViewById()是根据id创建一个view,还是返回在onCreate里已经创建的view?
茫茫大海,没有指南针,我们只能迷失在苍苍大海之中。
哎?这就不对了,你说郑和下西洋环游地球最终返回中国,这是一个奇迹。可是,在 没有通讯仪器的古代,加上单打独斗独闯七大洲,没有方向概念克不行啊。。。
所以,为了您的安全,请带好指南针。 话题回来,我们这里有一个类似的东东,那就是在程序的海洋中旅行的人们耳熟能详的, 居家旅行必备的(名字就不用说了,这个大家都应该知道) http://developer.android.com/reference
那么这个doc告诉了我们什么呢?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 方法的作用就很有限了。
我们来看一下setContentView的文档。 Set the activity content from a layout resource. The resource will be inflated, adding all top-level views to the activity.
看到inflate这个词,应该想到另外一种findView之外构建activity页面的方法了。不难理解,inflate就是 建立一个新的android.view.View对象。结合 setContentView的定义,activity也是通过setContentView并 传入一个xml来构建整个activity的view对象以及子对象的!
就是说,在onCreate的setContentview 里,有一个contentview = viewInflater.Inflate();或者类似的东东。
所以,我们应该在ondestory把由setContentview创建的contentview置为null,就一劳永逸了。 但是,这句话我们看不到,因为在Activity父类里。 同样,我们也不能在ondestory把contentview = null; 因为是父类的私有字段!
经过一番思考,想出了一种方法,很多人应该也能感觉到,那就是setContentview(null) 通过这样的方法,改变父类Activity的contentview对象的引用,让oncreate的setContentview创建的 那个view对象失去引用,被GC掉。 然而,编译报错,NullPointerException。于是写了一个空的viewxml,命名view_null。 编译成功,运行正常。结果是,10个打开关闭一共消耗了0.6M的内存。


android中对于控件的background,src等资源不会随activity.this.finish()而消亡的,要通过如下方法来置空资源

假设控件名为fl

1. 通过控件得到其资源 BitmapDrawable bd = (BitmapDrawable)fl.getBackground();
2. 重新设置控件背景为空 fl.setBackgroundResource(0);
3. 设置callback为空 bd.setCallback(null);
4. 回收资源 bd.getBitmap().recycle();
5. 置空控件对象 fl = null;



http://blog.csdn.net/chen825919148/article/details/23843049


更多相关文章

  1. Android intent 传递对象以及返回刷新
  2. Android App性能优化——内存泄露以及内存优化
  3. android 上 webkit js 本地扩展之全局本地对象实现步骤
  4. 避免Android内存泄露
  5. android实现自定义控件及如何在其他项目中使用
  6. focusable ,focusableInTouchMode,控件焦点属性;Android 如何让Edit
  7. Android 动态增加控件(转)
  8. Android常用控件之SeekBar的使用
  9. Android开发实践:玩转EditText控件

随机推荐

  1. android系统对linux内核的主要补丁
  2. 如何使用GreenDAO 3.0
  3. AsyncTask的坑,Handler,Looper与MessageQue
  4. Android(安卓)MVP设计模式登录具体实现Ma
  5. Android(安卓)Makefile 文件讲解
  6. Android(安卓)BroadcastReceiver基础详解
  7. android下Service BroadcastReceiver与Al
  8. 25个有用的移动Web页面设计草图
  9. 【Android(安卓)Developers Training】 6
  10. 开发者必读jQuery Mobile入门教程