Android培训

亿元级外企Android培训企业

  • 全国服务监督电话4001118989
  • Android开发性能优化总结,Android开发内存、布局、编码和网络优化

    发布:Android培训  来源:Android教程  时间: 2017年05月05日

  • Android开发性能优化总结,Android开发内存、布局、编码和网络优化...

  • 本文大体分为四部分

    内存优化
    布局优化
    编码优化
    网络优化

    内存优化

    首先说一下内存泄漏和OOM:

    内存泄漏,因为不恰当的引用导致本该被释放的资源无法得到释放。
    OOM,新分配的内存大小加上已经占用的内存大小,超出了限制的内存大小。

    内存泄漏更多是因为我们的代码写的有问题,OOM更多是因为我们对我们应用内存的占用没有很好的把控。内存泄漏是导致OOM的一大元凶。
    内存优化分为5点来说:

    减少对象内存占用
    内存对象的复用
    避免内存泄漏
    合理的内存使用策略
    内存优化辅助工具

    一、减少对象内存占用

    使用更加轻量的数据结构。比如:ArrayMap/SparseArray是替代HashMap的好帮手。关于ArrayMap和SparseArray的使用:
    适合对象个数的数量级最好在千以内,因为他们的插入和删除的效率不够高。
    查找和插入使用的是二分查找。
    key类型是int时,请使用SparseArray因为它避免了自动装箱。
    避免使用Enum。官方说法是,相对于静态常量,枚举会消耗两倍以上的内存。并且在运行时还会产生额外的内存占用。在一个官方实例里,枚举占用的内存是静态常量的13倍,运行时内存占用是6倍。
    减少Bitmap对象的内存占用。对于创建出来的Bitmap对象通常有两个操作可以优化其内存占用。
    inSampleSize:在载入内存之前,计算一个合适的缩放比例。
    decodeformat:解码格式,ARGB_8888(每个像素4个字节,最高精度,有透明通道)、RGB_565(每个像素两个字节,无透明度)、ARGB_4444(deprecatedinApi13)、Alpah_8,不同的解码格式差别很大。根据情况选择合适的会比较好。
    使用更小的图片。拿到美工给的图,要留意大图直接被XML引用有时会出现InflationException,该异常的根本原因就是OOM。

    二、内存对象的复用

    复用系统自带的资源。系统自带了很多颜色、动画、样式、布局、图片。使用这些可以减少内存开销,但需注意版本差异性。
    ListView/GridView/RecyclerView内重复子View的复用。
    Bitmap对象复用。使用inBitmap来复用已经存在的内存区域。3.0之后出现,重用的bitmap大小和解码格式需要一致。4.4以后优化大小限制,只要小于或等于原bitmap的大小即可。可以维护一个有多种典型bitmap的对象池,使得后续bitmap创建都可以找到合适的复用模板。
    在频繁调用的方法外创建对象。如onDraw()方法会频繁调用,在里面做创建对象的操作会迅速增加内存使用,很容易引起频繁GC甚至是内存抖动。
    StringBuilder/StringBuffer。使用StringBuilder/StringBuffer来替代频繁的字符串拼接操作。

    三、避免内存泄漏

    Activity的泄漏。
    内部类引用导致。典型的如Handler。考虑尽量使用静态内部类,同时使用弱引用机制避免互相引用出现的泄漏。
    ActivityContext被传递到其他实例中,可能导致自身被引用发生泄漏。尽量使用ApplicationContext。除了和UI相关的,如显示弹窗、启动Activity、填充布局。参考AndroidContext。
    临时Bitmap对象的回收。临时创建一个相对比较大的bitmap对象,在经过变换获得新的bitmap对象之后,应尽快回收之前的bitmap。注意createBitmap()方法可能返回sourcebitmap,所以需要检查返回值是否和sourcebitmap相等。不等才可以对sourcebitmap执行recycle方法。
    监听器的注销。
    Cursor对象的及时关闭。
    缓存容器的对象泄漏。如4.0之前,把drawable添加到缓存容器,因为drawable和view的强引用很容易导致activity发生泄漏。
    WebView的泄露。Android的WebView存在很大的兼容性问题,WebView因为不同系统版本不同厂商都粗乃很大的差异,甚至标准的WebView存在内存泄漏的问题(09年发现,13年修复)。根治方法:为WebView使用新进程,通过AIDL进行通信,WebView所在进程根据业务需要在合适时机进行销毁。
    慎用static对象,static的生命周期和应用的进程保持一致,使用不当很可能导致内存泄漏。
    留意单例对象中不合理的引用。单例对象的生命周期和应用保持一致。

    四、合理的内存使用策略

    使用IntentService代替Service。
    谨慎使用largeheap。在清单文件的<application>节点设置largeHeap=true可以为应用生命一个更大的heap控件。会影响用户体验,并使GC运行时间更长,任务切换耗能增加。并且,在一些严格限制的机器上,largeHeap和通常的heapsize大小一样。你始终应该通过getMemoryClass()来检查实际获取到的heap大小。
    合适的缓存大小。结合可用内存大小等因素设置。
    onLowMemory()和onTrimMemory()。后者从4.0开始提供,提供了更为详细的系统内存占用级别。可以通过监测系统内存占用适当的释放自身的一些内存占用。
    选择合适的文件夹存放资源文件。图片会被拉伸以适应不同的设备。对于不希望被拉伸的图片,放在assets或nodpi目录下。
    对大内存分配做Try...Catch...操作。比如给解析大图时,使用trycatch,catch到OOM后将采样比例增加一倍再次尝试解析。
    慎用抽象编程。抽象需要同等量的代码用于可执行,这些代码会被mapping到内存中。
    使用nanoprotobufs序列化数据。Google设计,类似XML,比XML更加轻量快速简单。
    慎用依赖注入。通过扫描你的代码执行许多初始化操作,会导致你的代码需要大量的内存空间来mapping代码,而且mappedpages会长时间保留在内存中。
    慎用多进程。可以扩大应用的内存占用范围,但使用不当会导致显著增加内存。
    使用ProGuard剔除不需要的代码。
    慎用第三方库。很多功能会用不上。

    五、内存优化辅助工具

    facebook开源的LeakCanary,可用来监测内存泄漏
    AndroidMonitor,可以查看内存占用,可以查看指向,可以手动触发GC。分析内存泄漏的流程是
    手动触发GC
    查看JavaHeap
    点击AnalyzerTask即可进行内存泄漏的分析。

    布局优化

    分四个方面

    选择合适的根节点
    重用布局文件
    仅在需要时加载布局
    避免过度绘制

    一、选择合适的根节点

    Android在创建Activity时默认生成的布局为RelativeLayout,而新建布局时默认的根节点为LinearLayout。这是因为

    在复杂的布局中使用RelativeLayout可以降低布局嵌套,使布局比较扁平。也更加灵活。
    对于简单的布局,LinearLayout在不用处理weight属性的情况下,性能上是优于至少需要计算两次的RelativeLayout的。

    二、重用布局文件

    <include>标签的使用,要注意如果需要使用layout属性,必需先设置layout:width和layout:height
    <merge>标签的使用可减少不必要的视图嵌套:
    添加的子视图不需要针对父视图的属性,只是要添加到父视图上显示。根节点可为<merge>。
    比如在LinearLayout里include另外一个方向相同的LinearLayout,这个被include的视图的根节点就可以改为merge.

    三、仅在需要时加载布局

    <ViewStub>
    使用时调用inflate即可,也可以调用setVisibility(View.VISIBILITY)。
    注意:不支持<merge>标签的布局。
    四、避免过度绘制

    比如给根布局设置了图片背景,但是用户只能看到子View,根本就没有看到最下面的背景。但是背景仍要被绘制。这就是过度绘制。
    可以通过设置-开发者选项-显示GPU过度绘制来观察过度绘制。颜色越深的区域过度绘制越严重,蓝色最好,红色最差。

    去除不必要的背景设置。
    自定义view时,通过Canvas的clipRect()来绘制部分需要重绘的区域。

    五、小知识点

    android:drawableXXX属性。TextView控件可直接显示图片和文字。
    setCompoundDrawable(),代码中通过该方法实现第一个效果。
    android:divider,使用自带的分割线。
    space控件,可用于添加空白间隔,该控件不进行绘制。
    android:lineSpacingExtra="",android:text="aaa\nbbb\nccc"多行文字可使用TextView的行间距实现。
    Spannable,使用Spannable来为TextView设置强大的样式。

    编码优化

    几个点

    静态方法。将一项通用的功能写成静态方法,调用速度会提升15%-20%,同时不需要创建对象来调用该方法,也不用担心改变对象的状态(静态方法无法访问非静态字段)。
    避免创建不必要的对象
    静态最终常量。对基本数据类型以及String常量使用staticfinal修饰,会在dex文件的初始化器中进行初始化,会更快。
    多使用增强型for循环,但ArrayList使用传统循环方式。
    使用系统封装好的API。系统的API很多功能是通过底层汇编模式执行的,效率会比较高。如数组拷贝的功能,使用System.arrayCopy()会比使用循环一一赋值效率高9倍以上。
    避免在内部使用getter/setter。内部使用时,字段查找比方法调用效率高。

    网络优化

    工具:AndroidStudio有NetworkMonitor

    主要有:

    接口设置多样化,便于App可以以较少的请求来完成业务需求。
    使用Gzip压缩request和response,减少数据传输大小
    可以使用ProtocolBuffer来代替json、XML等
    合适的图片。获取图片时告知服务器宽高质量等来获取合适的图片资源。
    设置网络缓存,来取消不必要的网络请求。
    在网络良好的时候,对一些很有可能会进行操作的数据进行提前获取。
    弱网优化,AndroidEmulator可以设置网络速度和延迟来做弱网测试。可采取的措施如:不自动加载图片、先反馈后提交(如用户点赞,先给提交成功的反馈,记录下来之后提交)
  • 上一篇:Android Studio常用配置及使用技巧

    下一篇:Android有哪些权限?Android开发权限集合

网站导航
2001-2016 达内时代科技集团有限公司 版权所有 京ICP证8000853号-56