取经之路 - Android性能优化

在这里插入图片描述

Android性能 - 绘制

  • Android系统16毫秒发出一个信号,触发UI进行渲染
  • view的绘制保持在60帧每秒,绘制时间尽可能保持在16毫秒
  • 本质是较少onDraw的负担
  • 解决方法
    • onDraw中不能由耗时方法
    • 避免过多或者嵌套循环
    • 避免创建新的局部变量,大量的零时对象导致频繁的GC

Android性能 - 启动

  • 闪屏页

  • Android程序的启动分类

  • 冷启动

    1. 加载启动app
    2. 展示空白window页面
    3. 创建app进程
    4. 创建app对象
    5. 启动主线程
    6. 创建启动activity对象
    7. 加载view
    8. 布置屏幕
    9. 第一次绘制
  • 启动优化方向

    1. 替换window页面背景 <障眼法>

    2. 避免启动的密集初始化

      常常使用的multiDex初始化,第三方组件初始化

      利用欢迎页和闪屏页时间完成初始化

    3. 避免耗时操作和深嵌套布局

Android性能 - 布局

由于任何原因导致接收到VSYNC信号的时候无法完成本次刷新操作,就会产生掉帧的现象

  • 过度绘制

    • 一个像素在同一帧被绘制多次 (不可见的ui也被绘制,就是浪费资源)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VhztE3xp-1585153243684)(C:\Users\Primer4\Documents\学习笔记\1583509429660.png)]

  • 解决

    1. 去掉布局的背景色
    2. 去掉不必要控件的背景色
    3. 减少嵌套
      1. include 提高复用
      2. merge 减少自身一层嵌套
      3. viewsub 按需加载
    4. 约束布局
  • GPU渲染

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zg7bfBCJ-1585153243686)(C:\Users\Primer4\Documents\学习笔记\1583510951335.png)]

    1. 橙色 :GUP做的任务
    2. 红色 :绘制视图的多少
    3. 浅蓝色 :绘制图片
    4. 深蓝色 :更新视图
    5. 绿色1 :布局测量
    6. 绿色2 :动画
    7. 绿色3 :输入处理
    8. 深绿色: 主线程耗时操作

Android性能 - 内存

  • 内存泄漏

    • 那些无法被GC识别的对象一直占用内存,得不到回收
    • 逻辑上已经不会再使用的对象,但是实际上依然保持着引用
    • 内存被占用越多,GC越频繁,GC发生时所有线程都暂停,处理的对象多了就容易卡顿
  • 泄漏的场景

    • 集合类引用
    • 单例/静态变量 生命周期的长短不一致
    • 匿名内部类/非静态内部类(自动持有外部类的强引用 解决: 使用静态类)
    • 资源未关闭 (网络连接,文件流,evenbus取消注册)
    • 四种引用
  • Java内存

    1. 方法区:常量,类信息 <线程共享>
    2. 虚拟栈:每个方法由栈帧,存储方法信息 <线程私有,为Java方法服务>
    3. 本地栈:为本地方法服务
    4. 堆: 对象实例所在<线程共享>
    5. 程序计数器: 所执行的字节码行号指示器 <Java方法拥有,本地方法为空>
  • Java内存回收

    1. 标记清除 : 标记回收对象,清除被标记对象 <易产生大量碎片>

    2. 复制算法 :内存一分为二,一个现用,一个备用 <实际可用内存大小缩小为一半>

    3. 标记整理: 标记回收对象,整理(移动)存活对象 <避免内存碎片,避免一半内存的浪费 针对对象存活率较高的老年代>

    4. 分代收集: 根据对象的生命周期划分内存

      堆:

      ​ 新生代 ->大量对象死亡 -> 复制算法

      ​ 老年代 ->对象存活率高 -> 标记算法

  • 对象是否回收

    1. 引用计数

      引用对象,计数+1

      引用失效,计数 - 1

      缺点:不能解决相互循环引用

    2. 可达性分析

      以GCroot对象为根节点

      有可达引用链表示对象存活

  • Android内存

    • Dalvik虚拟机

      1. 加入JIT即时编译策略: 缺点①每次启动应用都要编译②运行时更耗电
    • ART虚拟机

      1. AOT编译策略,静态编译,安装程序的时候编译
      2. 改进GC过程
    • 两者混合编译

      1. 程序安装时dex不会被编译
      2. 运行时编译dex
      3. 手机充电或者空闲时进行AOT编译
    • 内存回收

      新生代->老年代->永久代

    • 共享内存

      Zygote的进程fork出来的程序进程

    • 分配和回收内存

Android性能 - 卡顿

60帧合适的显示速度,16ms内显示界面布局表示流畅画面

卡顿时候,帧率下降到30等,很明显的卡顿

卡顿的原因

  • UI线程中的耗时操作
    1. I/O读写
    2. 数据库访问
    3. 网络请求
  • 布局不合理
    1. 控件数量多
    2. 嵌套深
    3. overdraw
  • 内存异常
    1. 内存泄漏
    2. GC次数多 <那么CPU绘制时间就短>
  • 错误的异步操作
    1. 异步线程开启失误

寻找卡顿原因

  • stick mode

    检测程序中违例的情况

    1. 主线程进行I/O操作
    2. 主线程进行网络请求

    主要检测两大问题

    1. 线程策略 <线程使用不当>
    2. VM策略 <内存泄漏>

    使用

    if (IS_DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
      StrictMode.setVmPolicy(new VmPolicy.Builder().detectAll().penaltyLog().build());
    }
    

    在debug模式下使用

    查看日志

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jMHNTN5B-1585153243687)(C:\Users\Primer4\Documents\学习笔记\1583505975013.png)]

Android性能 - 异步

异步不包治百病,不正确使用异步会更卡顿

  • nice values线程优先级
    1. default UI线程
    2. background 后台线程
  • cgroups
    1. 控制和分离进程组
  • 使用
new Thread(new Runannable()).start()
  创建和销毁耗能大
  和UI线程具有相同的优先级,出现竞争
  匿名内部类持有外部引用,易内存泄漏
  缺乏线程管理
private class A extendes AysncTask<in,progress,result>{
   onPreExecute();//执行任务前
  doInBackground();//线程后台任务
  onProgressUpdate();//任务进度
  onPostExecute();//UI操作
  onCancelled();//取消异步操作
}

in 传入的参数
progress 进度
result 结果
	
	默认串行
	匿名内部类持有外部引用,内存易泄漏

Handler handler = new Handler(){
  handleMessage(msg);
};

	串行执行
	默认优先级和UI线程同级,出现竞争

IntentService

ThreadPoolExecutor

Android性能 - 瘦身

  • APK组成

    1. assets/ 静态文件
    2. lib/ os文件
    3. META-INF/ 签名信息
    4. res/ 资源文件
    5. AndroidManifest.xml 配置文件
    6. classes.dex Java字节码的产物
    7. resource.arsc 编译后的二进制资源文件
  • AS自带的 analyze APK工具

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZDg8O0e0-1585153243688)(C:\Users\Primer4\Documents\学习笔记\1583560318784.png)]

  • 反编译工具 class shark

    https://github.com/google/android-classyshark/releases

  • 如何瘦身

    1. 移除无用代码

    2. 移除无用库,相同库

    3. 启用Proguard

      稍用,规则繁琐

    4. 缩减方法数

    5. 移除无用资源

      layout

      drawable

    6. 图片压缩

      压缩网站 https://tinypng.com/

      AndroidStudio插件:TinyPngPlugin,能够批量地压缩项目中的图片,更加方便。

    7. png转jpg

      png无损

      png体积大

    8. 使用矢量图

      xml, svg

    9. 使用webp

    10. 网络资源

    11. so文件瘦身

    12. 使用7zip进行极限压缩

Android性能 - 电量

  • 工具 Battery Historian

  • 电量优化

    1. CPU时间片

    2. 网络传输

      数据压缩

      传输方式

      请求处理

      无网避免请

    3. GPS

      合适的location provider

      及时注销监听

      模块复用

    4. wake lock 不休眠锁

    5. 传感器

Android性能 - 网络

  • 网络问题
    1. 流量消耗
    2. 电量消耗
    3. 热修复
    4. 弱网
  • 网络监控
    1. network monitor 网络请求
    2. fiddler charles 抓包
  • 优化方向 <速度,流量,成功率>
    1. gzip压缩减少传输
    2. IP直连去除DNS解析
    3. webp格式的图片
    4. 缩略图
    5. 网络缓存
    6. 弱网判断特殊处理

Android性能 - 无响应

  • 分类
    1. 触摸或按键等待
    2. 广播不能规定完成
    3. 服务不能规定完成
  • 原因
    1. 主线程阻塞
    2. IO等待
    3. 其他程序影响
  • 出发场景
    1. 输入5s未响应完毕
    2. 前台广播10s内未完毕,后台20s
    3. 前台服务20s,后台服务200s
    4. 内容提供者publish 10s

Android性能 - Bitmap

  • bitmap内存模型

    Android2.2之前GC执行,主线程暂停;

    Android2.3之后,GC并发执行

    API 10 bitmap像素数据存放在 native内存,对象在dalvik heap;

    3.0~8.0 像素和对象都在native内存;

    8.0~now 像素又移到了native,对象和像素可以同时回收,新增hardware bitmap

  • bitmap回收

    2.2.3之前推荐使用bitmap.recycle()

    3.0之后复用bitmap

  • bitmap的复用

  • bitmap的加载

  • 推荐使用图片加载框架glide,piccasso等处理图片

  • bitmap优化

    • 图片质量压缩
    • 尺寸压缩
    • libjpeg.so压缩
  • bitmap相关知识

    • 大小
      • 8位->每个像素1字节
      • 16位->2字节->每ARGB通道4位
      • 32位->4字节->每ARGB通道8位
    • 占内存大小: = 1080* 1920* 4bit = y (M) (大小还受屏幕密度得影响: 三倍密度的计算-> 1080 1.5 1920* 1.5* 4=y **)

listview和recyclerview的区别

  • recycleview的adapter封装好了viewholder
  • layoutmanager管理滚动和循环利用
  • item的动画自定义
  • 点击事件需要自己实现
  • 缓存上
    • recycleview四级缓存
    • list view 二级缓存
  • recycleview的局部刷新
    • 避免过多无用的bindview
    • 找到特定的viewholder进行操作
    • adapter的notifyItemChanged(position)方法,并重写adapter的onBindViewHolder方法
发布了117 篇原创文章 · 获赞 23 · 访问量 1万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 自定义皮肤 设计师: ___KG

分享到微信朋友圈

×

扫一扫,手机浏览