天天看点

Android面试题总结(八)优化篇(内存优化和UI优化)

1.内存泄露和内存溢出分别是什么,他们之间有什么关系?

内存泄露是指保存了不可能再被访问的变量引用,导致垃圾回收器无法回收内存。

也就是说,在java中有些对象的生命周期是有限的,当他们完成了特定的逻辑后将会被垃圾回收;但是,如果在对象的生命周期本来该被垃圾回收时这个对象还被别的对象所持有引用,那就会导致内存泄露。

内存溢出是指虚拟机内存耗尽,无法为新对象分配内存,导致引用崩溃。典型的情况为加载多张大图,导致内存耗尽。

2.什么情况下会导致内存泄露?

(1)资源释放问题

      程序代码的问题,长期保持某些资源,如Context,Cursor,IO流的引用,资源得不到释放造成内存泄露。

(2)对象内存过大问题

       保存了多个好用内存过大的对象(如Bitmap,xml文件),造成内存超出

(3).static 关键字的使用问题

   static是java中的一个关键字,当用它来修饰成员变量时候、,那么改变量就属于该类,而不是该类的实例。所以用static修饰的变量,他的生命周期是很长的,如果用它来引用一些耗费资源过多的实例(Context的情况最多),这时候就要谨慎对待了

针对static的解决方案:

   <1>应该尽量避免static成员变量引用耗费过多的实例,比如Context。

   <2>Context尽量使用ApplicationContext,因为Application的Context的生命周期比较长,引用它不会出现内存泄露的问题。

   <3>使用WeakRefrence代替强引用。比如可以使用WeakRefrence<Context>mContextRef;

(4).线程导致内存溢出

  线程产生内存泄露的主要原因在于线程生命周期的不可控。

针对这种线程导致的内存泄露问题的解决方案:

  <1>将线程的内部类,改为静态内部类(因为费静态内部类拥有外部类对象的强引用,而静态类则不拥有)。

   <2>在线程内部采用弱引用保存Context引用

(5).查询数据库没有关闭cursor

程序中经常会进行查询数据库的操作,但是经常会有使用完毕Cursor后没有关闭的情况。如果我们查询的结果集比较小,对内训的消耗不容易被发现,只有在长时间的大量操作的情况下才最出现内存问题,这样就会给以后的测试和问题排查带来困难和风险。

(6).构造Adapter没有复用convertview

在使用ListView的时候通常会使用Adapter,那么我们应该尽可能呢的使用ConvertView

为什么要复用convertView?

当convertView为空的时候,用setTag()方法为每个View绑定一个存放空间的ViewHolder对象。当convertView不为空。重复利用已经创建的view的时候,使用getTag()方法获取绑定的ViewHolder对象,这样就避免了findViewById对空间的层层查询,而是快速定位到控件。

(7).Bitmap不再使用时没有调用recycle()释放内存

     有时候我们会手动的操作Bitmap对象,如果一个Bitmap对象比较占用内存,当它不在被使用的时候,可以调用Bitmap.recycle()方法回收此对象的像素所占用的内存,但这不是必须的,是情况而定

3.如果对android内存进行优化?

 (1)Bitmap OOM(图片优化)

     缩放性能优化,缓存性能优化,重用性能优化,PNG压缩性能优化,选择性加载优化

  (2)ListView优化

  (3)UI Review(视图UI优化)

   (4)使用ThreadPool线程池而不是每次new Thread

    (5)String字符串优化

    (6)减少不必要的全局变量

     (7)Cursor(游标)回收

      (8)Receiver(接收器)回收

       (9)Stream/File(流/文件)回收

       (10)避免内部getters/Setters

       (11)for循环

4.String字符串优化

最常见的例子就是当你要频繁操作一个字符串时。使用StringBuffer代替String。

还比如:使用int数组而不是Integer数组。

避免创建短命的临时对象,减少对象的创建就能减少垃圾收集,进而减少对用户体验的影响。

5.UI视图优化

减少视图层级,可以有效的减少内存消耗,因为视图是一个树形结构,每次刷新和渲染都会遍历一次

(1)ViewStub标签可以使UI在特殊情况下,只管效果类似于设置View的不可见性,但是其最大意义在于被整各标签所包裹的vIEWS在默认状态下不会占用任何内存空间。

(2)Merge

单独将<merge/>标签做个介绍,是因为它在优化UI结构时起到很重要的作用。目的是通过删减多余或者额外的层级,从而优化整个Android Layout结构。核心功能就是减少冗余的层次从而达到优化UI的目的

(3)include

可以通过这个标签直接加载外部的xml到当前结构中,是复用UI资源的常用标签

(4)尽量使用相对布局

6.ListView优化

(1)Item布局,层级越少越好,使用hierarchyview工具查看优化

(2)复用convertView

(3)使用ViewHolder

(4)item中有图片时,异步加载

(5)快速滑动时,不加载图片

(6)item中有图片时,应对图片进行适当的压缩

(7)实现数据的分页加载

7.性能优化工具的使用

MAT,LearkCanary,Memory Monitor,Allocation Tracking,Heap Tool,hierarchyviewer布局检测工具

第三方分析工具

 MemoryAnalyzer,GT Home,iTest