Android学习十二周_内存、视图和电量优化

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cqupt2011214692/article/details/51530526

1、overdraw

1、overdraw的概念
overdraw发生在应用每次请求在其它物体上绘制内容的时候。例如:一个白色背景的窗口,在它上面有一个按钮。当系统绘制按钮时,要绘制在已存在的白色背景上,这就是overdraw。

2、如何查看overdraw
在Anroid的开发者工具中勾选上Show GPU overdraw。
该工具会使用三种不同的颜色绘制屏幕,来指示overdraw发生在哪里以及程度如何,其中:
没有颜色: 意味着没有overdraw。像素只画了一次。
蓝色: 意味着overdraw 1倍。像素绘制了两次。大片的蓝色还是可以接受的(若整个窗口是蓝色的,可以摆脱一层)。
绿色: 意味着overdraw 2倍。像素绘制了三次。中等大小的绿色区域是可以接受的但你应该尝试优化、减少它们。
浅红: 意味着overdraw 3倍。像素绘制了四次,小范围可以接受。
暗红: 意味着overdraw 4倍。像素绘制了五次或者更多。这是错误的,要修复它们。

3、优化方法
总的原则就是:尽量避免重叠不可见元素的绘制去除不需要的背景资源
在theme中添加 Android:windowbackground=”null”; 在Activity中设置getWindow().setBackgroundDrawable(null)
这个方法要在setContentView()之后,因为getWindow().setBackground(Drawable)会讲这里的Drawable设置到DecorView的background,默认是0xff000000,而setContentView才会第一次初始化phoneWindow的DecorView;
分段设置背景
有时候为了方便会先给Layout设置一个整体的背景,再给子View设置背景,这里也会造成重叠,如果子View宽度mach_parent,可以看到完全覆盖了Layout的一部分,这里就可以通过分别设置背景来减少重绘。

2、内存优化

  • 即时编译(Just-in-time Compilation,JIT),又称动态转译(Dynamic Translation),是一种通过在运行时将字节码翻译为机器码,从而改善字节码编译语言性能的技术。即时编译前期的两个运行时理论是字节码编译和动态编译。Android原来Dalvik虚拟机是作为一种解释器实现,新版(Android2.2+)将换成JIT编译器实现。性能测试显示,在多项测试中新版本比旧版本提升了大约6倍。
    避免创建不必要的对象

  • 就像世界上没有免费的午餐,世界上也没有免费的对象。虽然gc为每个线程都建立了临时对象池,可以使创建对象的代价变得小一些,但是分配内存永远都比不分配内存的代价大。如果你在用户界面循环中分配对象内存,就会引发周期性的垃圾回收,用户就会觉得界面像打嗝一样一顿一顿的。所以,除非必要,应尽量避免尽力对象的实例。下面的例子将帮助你理解这条原则:当你从用户输入的数据中截取一段字符串时,尽量使用substring函数取得原始数据的一个子串,而不是为子串另外建立一份拷贝。这样你就有一 个新的String对象,它与原始数据共享一个char数组。 如果你有一个函数返回一个String对象,而你确切的知道这个字符串会被附加到一个StringBuffer,那么,请改变这个函数的参数和实现方式, 直接把结果附加到StringBuffer中,而不要再建立一个短命的临时对象。

  • 一个更极端的例子是,把多维数组分成多个一维数组:
      int数组比Integer数组好,这也概括了一个基本事实,两个平行的int数组比 (int,int)对象数组性能要好很多。同理,这试用于所有基本类型的组合。如果你想用一种容器存储(Foo,Bar)元组,尝试使用两个单独的 Foo[]数组和Bar[]数组,一定比(Foo,Bar)数组效率更高。(也有例外的情况,就是当你建立一个API,让别人调用它的时候。这时候你要注重对API接口的设计而牺牲一点儿速度。当然在API的内部,你仍要尽可能的提高代码的效率)

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

  • 静态方法代替虚拟方法

  • 如果不需要访问某对象的字段,将方法设置为静态,调用会加速15%到20%。这也是一种好的做法,因为你可以从方法声明中看出调用该方法不需要更新此对象的状态。

  • 避免内部Getters/Setters
    在源生语言像C++中,通常做法是用Getters(i=getCount())代替直接字段访问(i=mCount)。这是C++中一个好的习惯,因为编译器会内联这些访问,并且如果需要约束或者调试这些域的访问,你可以在任何时间添加代码。而在Android中,这不是一个好的做法。虚方法调用的代价比直接字段访问高昂许多。通常根据面向对象语言的实践,在公共接口中使用Getters和Setters是有道理的,但在一个字段经常被访问的类中宜采用直接访问。无JIT时,直接字段访问大约比调用getter访问快3倍。有JIT时(直接访问字段开销等同于局部变量访问),要快7倍。
  • 将成员缓存到本地

3、电量优化

下面一些措施能够显著减少电量的消耗:

  • 我们应该尽量减少唤醒屏幕的次数与持续的时间,使用WakeLock来处理唤醒的问题,能够正确执行唤醒 操作并根据设定及时关闭操作进入睡眠状态。
  • 某些非必须马上执行的操作,例如上传歌曲,图片处理等,可以等到设备处于充电状态或者电量充足的时候才进行。
  • 触发网络请求的操作,每次都会保持无线信号持续一段时间,我们可以把零散的网络请求打包进行一次操作,避免过多的无线信号引起的电量消耗。关于网络请求引起无线信号的电量消耗。
  • 检查全部唤醒锁, 是否存在冗余或者无用的位置。
  • 集中相关的数据请求, 统一发送; 精简数据, 减少无用数据的传输。
  • 分析和统计等非重要操作, 可以在电量充足或连接WIFI时进行, 参考JobScheduler。
  • 精简冗余的服务(Service), 避免长时间执行耗电操作。
  • 注意定位信息的获取, 使用后及时关闭。

猜你喜欢

转载自blog.csdn.net/cqupt2011214692/article/details/51530526