Android性能优化典范

作者: 小红军storm | 来源:发表于2018-12-09 21:16 被阅读58次

    后期我会面试50家互联网公司,不断总结完善和思考,写出一本完美的安卓面试书籍,大家支持我吗?

    目录

    1、内存优化
    2、ui优化
    3、网络优化
    4、启动优化

    1、内存优化

    1.1、解决所有的内存泄漏

    1.1.1、内存泄漏:

    堆上分配的对象已经不会再使用,但是GC收集器无法对其进行回收,此对象被强应用所引用 。

    1.1.2、GC收集器原理:

    可达性算法:从GCRoot对象为起点,向下搜索,可到达的对象是称为GC可达,GC收集器不会回收,不可到达的对象称为不GC不可达,是GC收集器回收的对象。

    GCRoot对象:
    (1)、虚拟机栈(栈帧找那个的局部变量表)中的对象;
    (2)、方法区中类静态变量引用的对象;
    (3)、方法区中常量引用的对象。

    1.1.3、常见的内存泄漏实例

    (1)、单例造成的内存泄漏


    单例造成内存泄漏

    单例类的实例是静态的,如果需要其构造方法需要传递一个context,如果传入的是 Activity 的 Context,当传入 Activity 就会造成泄漏了。
    解决方法:this.context = context.getApplicationContext();// 使用Application 的context。

    (2)、内部类造成的内存泄漏


    内部类创建静态对象导致内存泄漏

    在Activity中有一个内部类,如果创建了这个内部类的静态对象,Activity关闭的时候,由于内部类会持有外部类的引用,内部类静态对象会持有外部类Activity的引用,导致Activity发生内存泄漏。
    解决方法:将该内部类设为静态内部类,如果该内部类需要持有外部类的引用,则使用软引用/弱引用,在使用外部类的引用之前需进行空判断。

    (3)、异步线程造成的内存泄漏


    异步线程造成内存泄漏

    在Activity中有一个开启一个线程执行一个runnable,这个runnable是内部类就会持有外部类Activity的引用,如果线程的生命周期比Activity的生命周期长,就不会导致Activity内存泄漏。
    解决方法:同上

    (4)、Handler 造成的内存泄漏


    handler造成内存泄漏

    在Activity中声明一个内部类handler,当使用这个handler发送一个延迟消息时,此消息执行前,Activity关闭会造成内存泄漏。
    解决方法:同上

    (5)资源未关闭造成内存泄漏
    对于使用了BraodcastReceiver,ContentObserver,File,游标 Cursor,Stream,Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。

    1.1.4、内存泄漏检测方案

    LeakCanary原理:

    1. LeakCanary在一个Fragment或者Activity onDestory的时候,创建一个弱引用 KeyedWeakReference 到要被监控的对象。

    2. 然后在后台线程检查引用是否被清除,如果没有,调用GC。

    3. 如果引用还是未被清除,把 heap 内存 dump 到 APP 对应的文件系统中的一个 .hprof 文件中。

    4. 在另外一个进程中的 HeapAnalyzerService 有一个 HeapAnalyzer 使用HAHA 解析这个文件。

    5. 得益于唯一的 reference key, HeapAnalyzer 找到 KeyedWeakReference,定位内存泄露。

    6. HeapAnalyzer 计算 到 GC roots 的最短强引用路径,并确定是否是泄露。如果是的话,建立导致泄露的引用链。

    1.2、避免内存抖动

    内存抖动代表频繁GC,会占用程序执行时间,造成页面卡顿等性能问题。

    1.2.1、避免内存抖动的方式:

    (1)、避免在onDraw中创建Paint、Bitmap对象等;
    (2)、避免在循环中创建临时对象;
    (3)、避免在scrollListener中创建对象。

    1.3、内存抖动检测方法

    (1)、使用Android profiler 进行观察,如果发下内存剧增剧减则是GC时间,可查看GC时间段的内存,找出重复创建的大量对象,进行优化(例子:在recycleview中获取距离屏幕的距离时,创建大量对象)。

    1.3、图片优化

    (1)、网络图片:使用网络裁剪服务,获取适当的图片加载。
    (2)、本地图片:使用Tinypng深度压缩,必要时进行裁剪。
    (3)、使用web格式代替png、jpeg格式。
    (4)、使用Fresco对图片进行管理。

    1.3.1、fresco对内存的管理:

    (1)、在5.0以下系统,Bitmap缓存位于ashmem,这样Bitmap对象的创建和释放将不会引发GC,更少的GC会使你的APP运行得更加流畅。5.0及其以上系统,相比之下,内存管理有了很大改进,所以Bitmap缓存直接位于Java的heap上。
    (2)、当应用在后台运行时,该内存会被清空。

    1.4、使用优化的数据结构

    2、ui优化

    2.1、分析布局,减少布局嵌套或者替换消耗性能少的布局

    2.2、使用include+merge减少布局层级

    2.3、使用viewstub提供按需加载

    3、网络优化

    3.1、网络速度:

    正常一条网络请求需要经过的流程是这样:
    (1)、DNS 解析,请求DNS服务器,获取域名对应的 IP 地址;
    (2)、与服务端建立连接,包括 tcp 三次握手,安全协议同步流程;
    (3)、连接建立完成,发送和接收数据,解码数据。

    这里有明显的三个优化点:

    3.1、IP直连或者HTTPDNS;
    3.2、开启 keep-alive进行连接复用;
    3.3、减少请求和返回数据的大小;

    (1)、请求和返回数据做Gzip压缩;
    (2)、精简数据格式;
    (3)、按需加载图片(图片裁剪,也可按网络状态返回不同分辨率的图片);

    3.4、数据缓存;

    3.2、网络优化补充:

    3.4、请求打包;(如埋点统计)
    3.5、协议优化;(如使用优化的的更好的http2,请求头压缩)
    3.6、断点续传。

    4、启动优化

    4.1、异步加载一:Application中加入异步线程

    4.2、异步加载二:MainActivity中加入异步线程

    4.3、 延迟加载功能:首屏绘制完成之后加载

    4.4、动态加载布局:主布局文件优化

    4.5、主布局文件深度优化

    4.6、 功能代码深度优化

    相关文章

      网友评论

        本文标题:Android性能优化典范

        本文链接:https://www.haomeiwen.com/subject/fiimqqtx.html