首页 > 其他分享 >史上最全Android性能优化方案解析

史上最全Android性能优化方案解析

时间:2023-06-22 11:06:21浏览次数:44  
标签:泄漏 绘制 最全 布局 内存 使用 Android 解析 优化


Android中的性能优分为以下几个方面:

布局优化

网络优化

安装包优化

内存优化

卡顿优化

启动优化

……

一.布局优化

布局优化的本质就是减少View的层级。常见的布局优化方案如下:

  • 在LinearLayout和RelativeLayout都可以完成布局的情况下优先选择LinearLayout,可以减少View的层级,但是注意相同组件可能RelativeLayout绘制时间长
  • 使用 < include > 标签将常用的布局组件共同的部分抽取出来,以便复用。
  • 通过 < ViewStub > 标签来加载不常用的布局,延迟加载(需要的时候在activity中加载出来)
  • 使用 < Merge > 标签来减少布局的嵌套层次

二.绘制优化

绘制优化是指View的onDraw方法要避免执行大量的操作,这主要体现在两个方面:

1.onDraw中不要创建新的局部对象。

因为onDraw方法可能会被频繁调用,这样就会在一瞬间产生大量的临时对象,这不仅占用了过多的内存而且还会导致系统更加频繁gc,降低了程序的执行效率。

2.onDraw方法中不要做耗时的任务,

不能执行成千上万次的循环操作,尽管每次循环都很轻量级,但是大量的循环仍然十分抢占CPU的时间片,这会造成View的绘制过程不流畅。

按照Google官方给出的性能优化典范中的标准,View的绘制频率保证60fps是最佳的,这就要求每帧绘制时间不超过16ms(16ms = 1000/60),虽然程序很难保证16ms这个时间,但是尽量降低onDraw方法中的复杂度总是切实有效的。

三.网络优化

常见的网络优化方案如下:

  • 尽量减少网络请求,能够合并的就尽量合并
  • 避免DNS解析,根据域名查询可能会耗费上百毫秒的时间,也可能存在DNS劫持的风险。可以根据业务需求采用增加动态更新IP的方式,或者在IP方式访问失败时切换到域名访问方式。
  • 大量数据的加载采用分页的方式
  • 网络数据传输采用GZIP压缩
  • 加入网络数据的缓存,避免频繁请求网络
  • 上传图片时,在必要的时候压缩图片

四.安装包优化

  • 安装包优化的核心就是减少apk的体积,常见的方案如下:
  • 减少应用中不必要的资源文件,比如图片,在不影响APP效果的情况下尽量压缩图片,有一定的效果
  • 在使用了SO库的时候优先保留v7版本的SO库,删掉其他版本的SO库。原因是在2018年,v7版本的SO库可以满足市面上绝大多数的要求,可能八九年前的手机满足不了,但我们也没必要去适配老掉牙的手机。实际开发中减少apk体积的效果是十分显著的,如果你使用了很多SO库,比方说一个版本的SO库一共10M,那么只保留v7版本,删掉armeabi和v8版本的SO库,一共可以减少20M的体积。
  • res资源优化
    (1)只使用一套图片,使用高分辨率的图片。
    (2)UI设计在ps安装TinyPNG插件,对图片进行无损压缩。
    (3)svg图片:一些图片的描述,牺牲CPU的计算能力的,节省空间。使用的原则:简单的图标。
    (4)图片使用WebP(https://developers.google.com/speed/webp/)的格式(Facebook、腾讯、淘宝在用。)缺点:加载相比于PNG要慢很多。但是配置比较高。工具:http://isparta.github.io/
    (5)使用tintcolor(android - Change drawable color programmatically)实现按钮反选效果。
  • 代码优化
    (1)实现功能模块的逻辑简化
    (2)Lint工具检查无用文件将无用的资源列在“UnusedResources: Unused resources”,删除。
    (3)移除无用的依赖库。
  • lib资源优化
    (1)动态下载的资源。
    (2)一些模块的插件化动态添加。
    (3)so文件的剪裁和压缩。
  • assets资源优化
    (1)音频文件最好使用有损压缩的格式,比如采用opus、mp3等格式,但是最好不要使用无损压缩的音乐格式
    (2)对ttf字体文件压缩,可以采用FontCreator工具只提取出你需要的文字。比如在做日期显示时,其实只需要数字字体,但是使用原有的字体库可能需要10MB大小,如果只是把你需要的字体提取出来生成的字体文件只有10KB
  • 代码混淆。
  • 使用proGuard 代码混淆器工具,它包括压缩、优化、混淆等功能。
  • 插件化
  • 可将功能模块放服务器,需要用时再加载。
  • 7z极限压缩

五.Android内存优化

1.Android内存管理机制

Android应用都是在Android虚拟机上运行的,内存分配和垃圾回收都是由Android虚拟机来完成的。

2.常见的内存泄漏

其实内存泄漏的本质就是较长生命周期的对象引用了较短生命周期的对象。

2.1 内存泄露

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

  • 静态变量导致的内存泄漏
    解决办法:将内部类设为静态内部类或独立出来;使用context.getApplicationContext()。
  • 单例模式导致的内存泄漏
    解决办法:传参context.getApplicationContext()。
  • 属性动画导致的内存泄漏
    解决办法:在Activity.onDestroy()中调用Animator.cancel()停止动画。
  • Handler导致的内存泄漏
    解决办法:使用静态内部类+WeakReference弱引用;当外部类结束生命周期时清空消息队列。
  • 线程导致的内存泄漏
    解决办法:将AsyncTask和Runnable设为静态内部类或独立出来;在线程内部采用弱引用保存Context引用。
  • 资源未关闭导致的内存泄漏
    解决办法:在Activity销毁的时候要及时关闭或者注销。例如:
    ① BraodcastReceiver:调用unregisterReceiver()注销;
    ②Cursor,Stream、File:调用close()关闭;
    ③Bitmap:调用recycle()释放内存(2.3版本后无需手动)。
  • Adapter导致的内存泄漏
    详情:不使用缓存而只依靠getView() 每次重新实例化Item,会给gc制造压力。
    解决办法:在构造Adapter时使用缓存的convertView。
  • WebView导致的内存泄漏。
    详情:WebView比较特殊,即使是调用了它的destroy方法,依然会导致内存泄漏。
    解决办法:其实避免WebView导致内存泄漏的最好方法就是让WebView所在的Activity处于另一个进程中,当这个Activity结束时杀死当前WebView所处的进程即可,我记得阿里钉钉的WebView就是另外开启的一个进程,应该也是采用这种方法避免内存泄漏。
  • 集合类泄漏
    详情:比如全局map等有静态应用,最后没有做删除。
    解决办法:在onDestry时回收不需要的集合。

2.2 扩大内存

大厂的SDK可能内存泄漏会少一些,但一些小厂的SDK质量也就不太靠谱一些。那应对这种我们无法改变的情况,最好的办法就是扩大内存。

扩大内存通常有两种方法:

  • 一个是在清单文件中的Application下添加largeHeap="true"这个属性,另一个就是同一个应用开启多个进程来扩大一个应用的总内存空间。
  • 第二种方法其实就很常见了,比方说我使用过个推的SDK,个推的Service其实就是处在另外一个单独的进程中。
  • Android中的内存优化总的来说就是开源和节流,开源就是扩大内存,节流就是避免内存泄漏。

2.3 检测、分析内存泄漏的工具

  • MemoryMonitor:随时间变化,内存占用的变化情况
  • MAT:输入HRPOF文件,输出分析结果
  • a. Histogram:查看不同类型对象及其大小
  • b.DominateTree:对象占用内存及其引用关系
  • c.MAT使用教程
  • LeakCanary:实时监测内存泄漏的库(LeakCanary原理)

六.卡顿优化方案

  • 不要在主线程进行网络访问/大文件的IO操作
  • 绘制UI时,尽量减少绘制UI层次;减少不必要的view嵌套,可以用Hierarchy Viewer工具来检测,后面会详细讲;
  • 当我们的布局是用的FrameLayout的时候,我们可以把它改成merge,可以避免自己的帧布局和系统的ContentFrameLayout帧布局重叠造成重复计算(measure和layout)
  • 提高显示速度,使用ViewStub:当加载的时候才会占用。不加载的时候就是隐藏的,仅仅占用位置。
  • 在view层级相同的情况下,尽量使用 LinerLayout而不是RelativeLayout;因为RelativeLayout在测量的时候会测量二次,而LinerLayout测量一次,可以看下它们的源码;
  • 删除控件中无用的属性;
  • 布局复用.比如listView 布局复用
  • 尽量避免过度绘制(overdraw),比如:背景经常容易造成过度绘制。由于我们布局设置了背景,同时用到的MaterialDesign的主题会默认给一个背景。这时应该把主题添加的背景去掉;还有移除
  • XML 中非必须的背景
  • 自定义View优化。使用 canvas.clipRect()来帮助系统识别那些可见的区域,只有在这个区域内才会被绘制。也是避免过度绘制.
  • 启动优化,启动速度的监控,发现影响启动速度的问题所在,优化启动逻辑,提高应用的启动速度。比如闪屏页面,合理优化布局,加载逻辑优化,数据准备.
  • 合理的刷新机制,尽量减少刷新次数,尽量避免后台有高的 CPU 线程运行,缩小刷新区域。

七.耗电优化

耗电的原因其实很多,这里我就讲一下几种优化方案,优化方案的反面就是他的原因了,几种优化方案如下:

  • 合理的使用wake_lock锁,wake_lock锁主要是相对系统的休眠(这里就是为了省电,才做休)而言的,意思就是我的程序给CPU加了这个锁那系统就不会休眠了,这样做的目的是为了全力配合我们程序的运行。有的情况如果不这么做就会出现一些问题,比如微信等及时通讯的心跳包会在熄屏不久后停止网络访问等问题。所以微信里面是有大量使用到了wake_lock锁。
  • 使用jobScheduler2,集中处理一些网络请求,有些不用很及时的处理可以放在充电的时候处理,比如,图片的处理,APP下载更新等等;
  • 计算优化,避开浮点运算等。
  • 数据在网络上传输时,尽量压缩数据后再传输,建议用FlatBuffer序列化技术,这个比json效率高很多倍,不了解FlatBuffer,建议找资料学习一下。

标签:泄漏,绘制,最全,布局,内存,使用,Android,解析,优化
From: https://blog.51cto.com/u_16163453/6534410

相关文章

  • Android App运行核心,Handler,Looper,Message
    目标在手机屏幕上显示指定的区域两种方法在已存在的图片上,绘制矩形,查看图片在全屏透明悬浮窗上直接画矩形已有图片绘制矩形读取图片letimgFilepath=files.path("./chess.png");letimg=images.read(imgFilepath);设置绘制区域letrect={left:52,top:20,rig......
  • android RecyclerView嵌套 RecyclerView 子item 和 父item点击事件如何处理
    前言经常会遇到列表嵌套列表的场景,那么父item和子item会有点击重叠该怎么处理尼?先上效果父adapteropenclassStoreListAdapter(layoutResId:Int,data:MutableList<StoreGoodsBean>):BaseQuickAdapter<StoreGoodsBean,BaseViewHolder>(layoutResId,data){//子adapt......
  • Android开发必备——注解
    前言阅读官方源码以及各类第三方框架时可以发现,很多地方都有注解,作为一名Android程序员,掌握注解属于必不可少的一项技能。1.什么是注解注解是以@符号开头的用来标识如类、字段、方法等的工具。说到注解,就不得不提另外一个概念——注释,两者其实都是做解释的功能,只不过注释是面向开......
  • Android 屏幕适配基础
    Pixels和dp、sp的区别不同屏幕密度下,1p显示的物理长度不同1dp在不同屏幕上显示相同的物理长度sp只用在字体上,和dp一样为了让在不同设备上有一致的显示效果单位尺寸搞清楚屏幕的各种单位含义,是屏幕适配的基础屏幕尺寸含义:手机对角线的物理尺寸单位:英寸(inch),1英寸=2.54cm屏幕尺寸......
  • Android 多任务配置
    Android多任务配置本篇文章是为了了解安卓中的多任务系统,了解安卓中Task的栈结构,以及怎么配置app的多任务,模仿微信小程序。多任务配置在安卓手机上,当我们打开微信小程序,可以看到小程序其实是一个独立的任务,这是怎么配置的呢。其实很简单,我们只需要在安卓项目的配置文件中,对Activit......
  • 好家伙66万字,又一份牛逼的Android笔记面世了
    前言很久以前,凭借四大组件、Java基础等知识,便可开开心心的开发,轻松地上岗。而随着Android的不断发展完善,各种组件库越来越成熟,学习资料越来越多,我们却慢慢地看不到方向。信息爆炸的时代,到底该如何提升自己?如何才能找到真正利己的信息?如何才能看清前路的方向?为此我专门找了一份《And......
  • 四年Android开发,在拉勾上投了十几个简历,没有一个面试邀请......药丸了
    在浏览某论坛的时候看到一名程序员吐槽:坐标杭州,四年Android开发一枚,技术不顶尖也不算差吧,这边加班太猛了,在考虑换一个岗位。在拉勾上投了十几个简历,全都是不合适,没有一个面试邀请!!!简历在拉勾上是开放的,竟然没有一个感兴趣的公司打电话给我。前年这个时候,接到的电话还是很多的,这才过......
  • Android视图加载优化——Factory2设置方法
    前言Factory2是直接继承于Factory,继续跟踪下Factory的源码,比Factory的功能更加强大。当我们新建Activity的时候,大部分情况是继承AppCompatActivity。提供了向后兼容性。本文将深入探索AppCompatActivity的视图加载,探索将xml布局文件中的TextView替换成AppCompatTextVi......
  • 6轮面试辛苦拿到阿里Android开发offer,却从22k降到15k,在逗我?
    一小伙工作快3年了,拿到了阿里云Android开发岗位P6的offer,算HR面一起,加起来有6轮面试了,将近3个月的时间,1轮同级+1轮Android用人部门leader+1轮Android组leader+1轮项目CTO+1轮HR+1轮HRBP。一路上各种事件分发机制、自定义View、handler原理、多线程、hashmap、手写算法、......
  • 三年Android开发就这水平?我还不如去招应届生
    公司前段缺人,也面了不少android程序员,结果竟然没有一个合适的。一开始瞄准的就是中级的水准,也没指望来大牛,提供的薪资在10-20k,面试的人很多,但平均水平很让人失望。看简历很多都是3年工作经验,但面试中,不提算法逻辑,仅仅基础的技术很多也知之不详,多数人数年的工作经验仅仅是用大量第三......