【Android】Android性能优化

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

一、布局优化


        系统在渲染 UI 的时候会消耗大量资源,所以一个好的布局不仅要具有好的视觉效果,更应该保有良好的使用体验。


1. Android UI 渲染机制


        人眼感觉到的动画流畅画面,帧数在40帧/秒到60帧/秒。

        Android 中,系统通过 VSYNC 信号触发对 UI 的渲染、重绘,间隔时间是16ms(1秒中显示60帧画面的单位时间)。如若 Android 程序让系统每次渲染的时间都保持在16ms之内,那么人们看到的 UI 界面将是非常流畅的。

        如若不能在16ms内完成绘制,那么就会造成丢帧现象,即当前该重绘的帧被未完成的逻辑阻塞。例如,一次绘制任务耗时20ms,那么在16ms系统发出 ASYNC 信号时就无法绘制,该帧就被丢弃,必须等待下次信号才继续开始绘制,导致16*2ms内都是显示同一帧画面,这就是画面卡顿。

        关于 Android 系统的检测 UI 渲染时间的工具使用,可以在 profile gpu rendering 查看。


2.避免 Overdraw


        Overdraw 即过度绘制,会浪费很多CPU、CPU资源。例如,系统默认会绘制Activity背景,而如果再给布局绘制了重叠的背景,那么默认的 Activity 背景就属于无效的过度绘制。

        Android 系统在开发者选项中提供了检测工具——“Enable GPU Overdraw”。激活后,可以通过界面上的颜色来判断 Overdraw 的次数。通过这个工具尽量优化绘图层次,增大蓝色区域,减少红色区域。


3.优化布局层级


        在 Android 中系统对 View 进行测量、布局和绘制时,都是通过对 View 树的遍历来进行操作的。如果一个 View 树高度太高,会严重影响测量、布局和绘制的速度,因此优化布局的另一个方法就是降低 View 树的高度。 Google 在 API 文档中建议 View 树的高度不宜超过 10 层。

        现在版本的 Android 中, Google 已经默认使用 RelativeLayout 来替代 LinuerLayout 作为默认根布局,原因是通过扁平的 Relative Layout 来降低通过 Linear Layout 嵌套所产生布局树的高度,从而提高 UI 渲染效率。


4.避免嵌套过多无用布局


        嵌套的布局会让 View 树的高度越来越高,因此在布局时,要根据自身布局特点选择不同的 Layout 组件,从而避免通过某一种不适当的 Layout 组件来实现功能时的局限性,造成嵌套过多的现象。


4.1.使用<include>标签重用 Layout


        通过<include>标签定义一个共同 UI 组件,可以避免代码的冗长和重复率,方便阅读。

        例如,要写一个共通的 Text View,可以在一个单独的 xml 文件中描述出来,并将 layout_width 和 layout_height 设置为 0dp,迫使开发者在使用时对宽高进行赋值,否则将无法看到这个组件,然后在引用的时候再重新为通用组件的宽高赋值。


4.2.使用<ViewStub>实现 View 的延迟加载


        ViewStub 在 UI 初始可见时不会显示,必须通过 mViewStub.setVisibility(View.VISIBLE); 或者 View inflateView = mViewStub.inflate(); 来显示布局,只有在显示的时候才会开始渲染。


二、内存优化


1.什么是内存


        由于 Android 应用的沙箱机制,每个应用所分配到的内存大小是有限度的,内存太低就会触发 LMK——Low Memory Killer 机制。

  • 寄存器(Registers)

        速度最快的存储场所,寄存器位于处理器内部,在程序中无法控制。

  • 栈(Stack)

        存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中。

  • 堆(Heap)

        堆内存用来存放由 new 创建的对象和数组。在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器(GC)来管理。

  • 静态存储区域(Static Field)

        静态存储区域就是指在固定的位置存放应用程序运行时一直存在的数据,Java 在内存中专门划分了一个静态存储区域来管理一些特殊的数据变量如静态数据变量。

  • 常量池(Constant Pool)

        JVM 虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的一个有序集合,包括直接常量(基本类型,String)和对其他类型、字段和方法的符号引用。


        关于栈和堆的概念

        栈存放基本数据类型(byte、short、int、long、float、double、boolean、char)和对象句柄,对于数字常量和字符串常量可以共享数据,对于堆来说栈分配资源速度快,当指定的某变量作用域结束后,这部分内存空间会马上被用作新的空间进行分配;

        堆是存放类类型、由 new 建立的对象内存空间。当对象的作用域结束后,这部分内存不会立即被回收,而是等待垃圾自动回收机制负责回收,回收速度慢。

        String  heapStr = new String("Lu"); //heapStr 存放在栈里,字符串 “Lu” 存放在堆内存

        String stackStr = "Lu"; //stackStr存放在栈里,字符串 “Lu” 存放在常量池中


2.内存优化


2.1.Bitmap 优化


  • 使用适当分辨率和大小的图片
        由于 Android 系统在做资源适配的时候会对不同分辨率文件夹下的图片进行缩放来适配相应的分辨率,如果图片分辨率与资源文件夹分辨率不匹配或者图片分辨率太高,就会导致系统消耗更多内存资源。同时,在适当的时候,应该显示合适大小的图片,例如在图片列表界面可以使用图片的缩略图 thumbnails,而在显示详细图片的时候再显示原图;或者在对图像要求不高的地方,尽量降低图片的精度。
  • 即使回收内存
        使用完 Bitmap 之后及时调用 bitmap.recycle() 方法释放内存资源。自 Android 3.0 之后, Bitmap 被放置在堆中,其内存由 GC 管理,就不再需要手动进行释放了。
  • 使用图片缓存

        通过内存缓存(LruCache)和硬盘缓存(DiskLruCache)可以更好地使用 Bitmap。


2.2.代码优化


        任何 Java 类都占用大约 500 字节的内存空间。创建一个实例大约消耗 15 字节的内存。

  • 对常量使用 static 修饰符
  • 使用静态方法,会比普通方法提高 15% 左右的访问速度
  • 减少不必要的成员变量,如果一个变量可以定义为局部变量,则尽量不要定义为成员变量
  • 减少不必要的对象,使用基础类型会更加节省资源,同时尽量避免创建短作用域的变量
  • 尽量不要使用枚举、迭代器
  • 对 Cursor、Receiver、Sersor、File、IO、网络连接等,要及时回收,关闭或者解注册
  • 避免使用 IOC 框架, IOC 通常使用注解、反射来实现
  • 使用 RenderScript、OpenGL 进行复杂的绘图操作
  • 使用 SurfaceView 来替代 View 进行大量、频繁的绘图操作
  • 尽量使用视图缓存,而不是每次都执行 inflate() 解析视图


2.3.内存泄露、内存溢出以及避免


详情见:http://blog.csdn.net/sko121/article/details/77747851

猜你喜欢

转载自blog.csdn.net/sko121/article/details/77726584