全部博文(403)
2012年(403)
分类: 嵌入式
2012-04-10 19:24:23
引起Android内存泄露有很多种原因,下面罗列了一些问题,以后会一一解决
1、构造Adapter时没有使用缓存convertView(衍生出ListView优化问题)
2、查询数据库游标没有关闭
3、Activity中生命周期对象大于Activity生命周期(关于Application Context与Activity Context)
4、Bitmap对象不使用时没有recycle掉(这里还有其他解决方案)
今天说的是第一种:如何使用缓存来优化ListView
因为如果不使用缓存convertView的话,调用getView时每次都会重新创建View,这样之前的View可能还没有销毁,加之不断的新建View势必会造成内存泄露。
使用getView时有3方案:(1)没有使用convertView,(2)使用convertView,(3)使用convertView+静态类ViewHolder
我做了一个测试,代码在下面,创建2000个View,从0拉到最后,计算总共耗,同时显示GC释放内存的大小,三种测试的结果如下:
注:这里先说下 GC_EXTERNAL_ALLOC freed 7K, 18% free 11153K/13511K, external 1632K/1672K, paused 89ms 的意思
在Dalvik中,为一个程序分配的内存要根据机型的不同而不同,一般为32M,而虚拟机会把这些内存分别分配给,JAVA使用的堆内存 (heap)和Nativie使用的内存(external)(即虚拟机中通过JNI调用本地Nativie的类中malloc分配的内存,如 Bitmap,java.nio.ByteBuffers)。不过两者不同共享,也就是说Native的内存不够用了,而JAVA内存够用时是不能向 JAVA申请的,必须向虚拟机申请才行,当虚拟机无法分配的时候就会报OOM的错误
freed 7k:表示GC已经释放了7K的内存
18% free 11153K/13511K:表示JAVA使用的堆内存(对象存在于此),18% free表示当前剩余18%的堆内存(heap memory),11153K表示当前已用的堆内存,13511K表示堆内存总共大小(网上有些文章这部分弄错了,很多转载都是同一个)
external 1632K/1672K:1632K表示已用external memory,总共1672K external memory(注意:这个可能只存在于Android 3.0之前)
paused 89ms:这里其实包括了两部分,一个是在调用GC之前暂停的时间,一个是调用GC后基本完成时暂停的时间
详细可参考:
(1)没有使用convertView
没有任何处理,不建议这样写。如果数据量少可以,但是如果列表项数据量很大的时候,会每次都重新创建View,设置资源,严重影响性能,所以从一开始就不要用这种方式
测试结果:
目前VM只为他们分配了5767K+518k的内存,而内存峰值是32M
刚开始时,而且heap memory只申请了5767K,已用内存3353K,注意数据大小的变化:耗时:167633055ns = 0.167633055秒
当拉到1000的时候,堆内存总计已经申请了9607K,已用内存7245K,明显已经比刚开始时要大了 ,耗时:3435241667ns=3.435241667秒
当拉到2000的时候,堆内存总计13511K,已用内存11153K,耗时:6660369835ns = 6.660369835秒
---------------------------我又创建了10000个ListView,测试后直到内存泄露,证明峰值却是是32M,而 不使用convertView导致的内存泄露,当内存泄露时手机会提示force close,并将错误写入/data/anr/traces.txt中,你可以adb pull下来查看具体信息
(2)使用convertView后的测试数据(优化后)
通过缓存convertView,convertView可以缓存可视范围内的convertView,当再次向下滑动时又开始更 新View,这种利用缓存convertView的方式可以判断如果缓存中不存在View才创建View,如果已经存在可以利用缓存中的View,这样会 减少很多View的创建,提升了性能
测试数据我还是用2000吧,10000太大了(一万年太久,只争朝夕)
测试结果:
这次一直拉到最后明显比刚才流畅多了,而且GC释放内存的次数也明显少了很多,最后用的时间和当前使用的内存也小很多,优化后的确好多了
当position为1000的时候,附近没怎么调用GC,用时:213653551ns=0.213653551秒,额,差距有点大,上面到达1000时用时达到3.43秒之多。
当position为2000的时候,已用内存只有3068K,堆总共内存6215K,而且external memory是0K,用时:378326396ns = 0.378326396秒,性能差距如此之大,都有点不敢相信。也不知道这种方式对不对,如有不妥的地方,还希望大牛能给出正确回答
(3)使用contentView+静态类ViewHolder类
通过convertView+ViewHolder来实现,ViewHolder就是一个静态类,使用 ViewHolder 的关键好处是缓存了显示数据的视图(View),加快了 UI 的响应速度。
当我们判断 convertView == null 的时候,如果为空,就会根据设计好的List的Item布局 (XML),来为convertView赋值,并生成一个viewHolder来绑定converView里面的各个View控件(XML布局里面的那些 控件)。再用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。(看下 面代码中)
如果convertView不为空的时候,就会直接用convertView的getTag(),来获得一个ViewHolder。
静态类ViewHolder
到这里,可能会有人问ViewHolder静态类结合缓存convertView与直接使用convertView有什么区别吗,是否重复了
在这里,官方给出了解释
提升Adapter的两种方法
To work efficiently the adapter implemented here uses two techniques:
-It reuses the convertView passed to getView() to avoid inflating View when it is not necessary
(译:重用缓存convertView传递给getView()方法来避免填充不必要的视图)
-It uses the ViewHolder pattern to avoid calling findViewById() when it is not necessary
(译:使用ViewHolder模式来避免没有必要的调用findViewById():因为太多的findViewById也会影响性能)
ViewHolder类的作用
-The ViewHolder pattern consists in storing a data structure in the tag of the view
returned by getView().This data structures contains references to the views we want to bind data to,
thus avoiding calling to findViewById() every time getView() is invoked
(译:ViewHolder模式通过getView()方法返回的视图的标签(Tag)中存储一个数据结构,这个数据结构包含了指向我们
要绑定数据的视图的引用,从而避免每次调用getView()的时候调用findViewById())
测试数据:(跟直接使用convertView数据相差不多)
当position为1000时,用时:199188216ns = 0.199188216秒,堆内存的时候也没比没有使用convertView理想的多
当position为2000时,用时:336669887ns = 0.336669887秒,比直接使用convertView的方式稍微好一点点,不过性能相差不多
如何快速优化网站关键词广西网站优化选哪家铜仁市网站优化厦门seo网站排名优化遂宁网站优化定做深圳机电网站优化技巧望江网站优化收费标准潍坊网站优化老p和br哪个有利于网站优化知名网站优化成功案例云鼎网站优化盐城滨海网站seo优化上海网站优化方案定制舟山网站的优化汉口如何优化网站推荐有没有基站优化的网站许昌网站推广优化找哪家网站刷点击量优化重庆专业网站优化产品介绍网站优化方法主题模型孟村网站优化网站描述会对优化产生什么影响网站排名优化一清云速捷引领虹口区360网站优化机构沧州快速网站优化于都seo网站优化沙头角如何免费做网站优化网站做优化评析易速达塘厦家具网站优化公司哪个好网站后台修改优化不成功天峨县网站seo优化排名南湖有效网站优化金华个人网站优化浙江省湖州市网站优化排名专用车机优化系统网站网站改版优化年终计划怎么优化网站丬云84速丬捷无锡网站优化有哪些泰州网站内容优化益阳网站优化哪家靠谱海兴优化网站如何降低同一个网站的优化网络营销怎么取代网站优化宜阳网站优化推广网站优化的失误网站推广seo优化价格龙华网站优化定制思明区网站优化价格佛山网站首页关键词优化费用铜仁企业网站优化深圳搜索网站优化营销招远市网站seo优化天水网站优化价格三明网站优化多少钱奉化高端网站优化天津百度网站优化河间市网站优化价格茶山镇网站优化南通市网站内部优化技术是什么桓台b2b 网站优化苏州网站搜索优化商城网站优化方法优化网站怎么加内锚文本吉林网站优化案例平凉网站优化推广公司哪家好德阳网站排名优化公司惠州网站优化电话多少高端网站优化好不好南陵网站优化排名重庆测试网站优化耗材舟山市网站seo优化排名网站seo优化 si支付行业网站优化营销广州网站优化是什么大型网站seo优化案例姚家园网站优化网站优化软件服务热线北票网站建设及优化优化网站排名联系t火24星惠网站优化后需要做哪些维护福州服务好的网站推广优化如何制作移动网站优化谢岗家具网站优化公司安康网站优化效果网站seo优化怎样收费优化网站排名咨询t火15星德州优化网站推广网站提速优化蓬莱网站关键词优化湖州优化网站哪家好许昌网站排名优化价格多少高柳网站优化公司网站有点排名怎么优化邵阳齐全的网站优化廊坊网站优化怎么收费南雄网站推广优化光明网站优化方案吉林网站搜索优化邯郸网站优化怎么开发招远市网站seo优化铁西区信息化网站建设优化价格佛山网站seo优化排名公司高要网站优化推广公司宝安网站关键词优化哪家好泸州网站优化专业公司优化网站设计好吗百度推广怎么做网站的优化宜昌优化网站建设合肥蜀山区网站优化细节优化网站网站优化排名方法有哪些网站抬头如何更适合优化成都正规的网站优化推广武汉网站优化公司推荐呈贡网站优化加盟淮滨网站优化怎么弄新人怎么优化网站网站优化-上海迪基特数字夜场网站优化平顶山网站建设优化公司电话吐鲁番市网站seo优化排名启东网站优化有哪些网站怎么优化询问y火18星来嘉兴网站优化简历云南网站优化推广营山县网站优化汕头公司网站关键词优化技巧网站关键词优化排名煌云速捷长春网站推广优化用什么方法晴隆seo网站优化高要优化网站排名工具网站优化公司怎么优化网站呢百度收录网站怎么做优化网站设计与优化策划珠海网站设计优化挤出机怎么做网站优化兰州网站排名优化电话网站优化的核心内容儋州网站优化公司安国企业网站优化井冈山网站按天优化开平市网站seo优化排名思南县网站优化营销惠济区网站怎么优化网站自然流量优化任丘网诚网络网站优化昆明百度网站优化网站跳出率高的优化济南正规网站优化哪家便宜新都区优化网站重庆南川服务好的网站优化泾县seo网站优化价格网站优化的两个层次南京企业网站优化哪家快网站关闭对优化有什么影响永济网站关键词优化景洪网站优化开发如何优化英语网站网站排名优化 需周o斯方法网站优化人员安排深圳全国网站优化服务如何广东很好的网站优化用户体验沧州快速网站优化网站优化专业优化外包哪家好公司网站优化成功案例网站建设过程中的优化环保节能网站优化案例江宁区百度网站优化关键词临沂网站制作优化培训万载县网站优化推广襄汾县网站seo优化排名网站内部结构对优化有什么影响深圳怎样做好网站优化比较好湖北网站优化推广哪家好企业网站做seo优化有教学吗怎么利用自媒体做网站优化最好优化分类网站小企业网站优化的方法优化中遇到网站降权怎么办优化网站速度 的库河南百度网站快速排名优化技巧武汉薪酬优化网站网站优化需求分析学校网站关于优化及域名沈阳放心的服务行业网站优化模块网站可以优化吗焦作seo网站关键词优化江苏网站建设seo优化前端可以做的网站优化电子网站优化公司好吗支付行业网站优化引流江门seo网站优化运营网站建设优化保定廊坊专业的餐饮行业网站优化广安网站优化有哪些新设计网站怎么做优化网站优化文章收录技巧网站优化标题注意什么山东泰安网站优化公司联系方式