Android启动速度优化

1,android启动流程

image.png

1,点击桌面App图标,Launcher进程采用Binder向system\_server进程发送startActivity进程间通信
2,System\_server进程中的AMS服务获取到startActivity请求后,通过Socket发送创建进程的请求到Zygote进程
3,Zygote进程fork出新的子进程,即App进程
4,App进程,通过Binder IPC向system\_server发送attach Application请求
5,System——server进程在收到请求后,进行一系列代码调用最终向App进程发送scheduleLaunchActivity请求
6,App进程的binder线程(ApplicationThread)向主线程通过handler.LAUNCH\_ACTIVITY发送消息
7,主线程在收到Message后,通过反射机制创建handleLauchActivity.onCreate()等方法
8,至此,App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染结束后便可以看到App的主界面

image.png

2,App的启动状态

应用有三种启动状态,每种状态都会影响应用向用户显示所需的时间:冷启动、温启动与热启动

冷启动是指应用从头开始启动:系统进程在冷启动后才创建应用进程,发生冷启动的情况包括应用自设备启动后或系统终止应用后首次启动

热启动,在热启动中,系统的所以工作就是将Activity带到前台,只要应用的所以Activity仍主流在内存中,应用就不必重复执行对象初始化、布局加载和绘制

温启动包含了冷启动期间发生的部分操作;同时它的开销比热启动高,有许多潜在状态可视为温启动,例如

用户在退出应用后又重新启动应用,进程可能未销毁,继续运行,但应用需要执行onCreate()从头开始创建Activity

系统将应用从内存中释放,然后用户又重新启动它,进程和Activity需要重启,但传递onCreate()的已保存的实例savedinstanceState对于完成此任务有一定助益

启动耗时统计

Adb命令启动应用,一般会输入三个值:ThisTime、TotalTime与WaitTime

WaitTime:包括前一个应用Activity pause的时间和新应用启动的时间
ThisTime:表示一连串启动Activity的最后一个Activity的启动耗时
TotalTime:表示新应用启动的耗时,包括新进程的启动和Activity的启动,但不包括前一个应用Activity pause的耗时

image.png

image.png

image.png

CPU Profile

Call chart 根据时间线查看调用栈,便于观察每次调用是何时发生的
Flame Chart: 根据耗时百分比查看调用栈,便于发现总耗时很长的调用链
Top Down Tree:查看记录数据中所有方法调用栈,便于观察其中每一步消耗的精确时间
Bottom Up Tree:相对于Top Down Tree,能够更方便查看耗时方法如何被调用

启动优化相关

合理的使用异步初始化、延迟初始化、懒加载机制
启动过程避免耗时操作,如数据库I/O操作不要放在主线程执行
类加载优化:提前异步执行类加载
合理使用IdieHandler进行延迟初始化
简化布局

布局优化

层级优化 Measure、layout、draw这三个过程都包含自顶向下的view tree遍历耗时,如果视图层级太深自然需要更多的时间来完成整个测绘过程,从而造成启动速度慢、卡顿等问题,而onDraw在频繁刷新时可能多次出发,因此onDraw更不能做耗时操作,同时需要注意内存抖动,对于布局性能的检测,依然可以使用systrace与traceview按照绘制流程检查绘制耗时函数

Layout Inspector

在较早的时代SDK中有一个hierarchy viewer工具,但是早在Android studio3.1配套的SDK中就已经被弃用,现在应在运行时改用Layout Inspector来检查应用的视图层次结构

使用merge标签

当我们有一些元素需要被多处使用时,这时我们会考虑将其抽取成一个单独的布局文件,在需要使用的地方通过inClude加载
image.png

ViewStub标签

ViewStub标签的作用是用于懒加载布局,当系统碰到ViewStub标签的时候是不进行绘制处理(如measure、layout等),比设置View隐藏、不可见更高效

过度渲染

过度绘制是指系统再渲染单个帧得过程中多次再屏幕上绘制某一个像素,例如,如果我们有若干界面卡片堆叠再一起,每张卡片都会遮盖其下面一张卡片得部分内容,但是,系统仍然需要绘制堆叠中得卡片遮盖得部分

CPU过度绘制检查

手机开发者选项中能够显示过度渲染检查功能,通过对界面进行彩色编码来帮我们识别过度绘制

1,进入开发者选项(Developer Options)
2,找到调试CPU过度绘制(Debug GPU overdraw areas)
3,在弹出得对话框中,选择显示过度绘制区域(Show overdraw areas)

Android将按如下方式为界面元素着色

    真彩色:没有过度绘制
    蓝色:过度绘制1次
    绿色:过度绘制2次
    粉色:过度绘制3次
    红色:过度绘制4次或者更多次

卡顿与布局优化

Systrace

Systrace是android平台提供得一款工具,用于记录短期内得设备活动,该工具会生成一份报告,其中汇总了android内核中的数据,例如CPU调度程序、磁盘活动和应用线程。Systrace主要用来分析绘制性能方面的问题,在发生卡顿时,通过这份爆改可以只当当前整个系统所处的状态,从而帮助开发者更直观的分析系统瓶颈,改进性能

TraceView可以看出代码在运行时的一些具体信息,方法调用时长、次数、时间比率,了解代码运行过程的效率问题,从而针对性改善代码,所以可能导致卡顿的耗时方法也可以通过TraceView检测

要使用Systrace,需要先安装Python,安装完成后配置环境变量path,随后在命令行输入:python –version,进行验证

Systrace具体使用可以查看博客:www.jianshu.com/p/e73768e66…

执行Systrace可以选择自己感兴趣的category

gfx:Graphis图形系统,包括SerfaceFlinger,VSYNC消息,Texture,RenderThread等
input:input输入系统,按键或者触摸屏输入,分析滑动卡顿等
view:view绘制系统的相关信息,比如onMeasure,onLayout等,分析View绘制性能
am:ActivityManager调用的相关信息,分析Activity的启动,跳转
dalvik:虚拟机相关信息,分析虚拟机行为,如GC停顿
sched:CPU调度的信息,能看到CPU在每个时间段在运行什么线程,线程调度情况,锁信息
disk:IO信息
wm:WindowManager的相关信息
res:资源加载的相关信息

其实Systrace对于应用开发者来说,能看的并不多,主要用于看是否丢帧,与丢帧时系统以及我们应用大致的一个状态

image.png

image.png

我们在抓取systrace文件的时候,切记不要抓取太长时间,也不要太多不同操作

代开抓取的html文件,可以看到我们应用存在非常严重的掉帧,不借助工具直接用肉眼看到应用UI是看不出来的,如果只是单独存在一个红色或者黄色的都是没有关系的,关键是连续的红/黄色或者两帧间隔非常打那就需要我们去仔细观察,按“W”放大视图,在UIThread主线程上面有一条很细的线,表示线程状态

Systrace会用不同的颜色来标识不同的线程状态,在每个方法上面都会有对应的线程来标识目前线程所处的状态,通过查看线程状态我们可以知道目前的瓶颈是什么,是CPU执行慢还是因为Binder调用,又或是进行IO操作,又或是拿不到CPU时间片,通过查看线程状态我们可以知道目前瓶颈是什么,是CPU执行慢还是因为Binder调用,又或是进行IO操作,又或是拿不到CPU时间片

线程状态主要有下面几个

绿色:表示正在运行
    是否频率不够(CPU处理速度)
    是否跑在了小核上?(不可控,但实际上很多手机都会有游戏模式,如果我们应用是手游,那系统会优先把手游中的任务放到大核上跑)
蓝色:表示可以运行,但是CPU在执行其他线程
    是否后台有太多的任务在跑?Runable状态的线程状态持续时间越长,则表示CPU的调度越忙,没有及时处理到这个任务
    没有及时处理是因为频率太低?
紫色:表示休眠,一般表示IO

App层面监控卡顿

systrace可以让我们了解应用所处的状态,了解应用因为什么原因导致的,若需要准确分析卡顿发生在什么函数调用,资源占用情况如何,目前主要有两种有效的app监控方式

1,利用UI线程的Looper打印的日志匹配
2,使用Choreographer.FrameCallback

通过ChoreographerHelper可以实时计算帧率和掉帧数,实时监测App页面的帧率数据,发现帧率过低,还可以自动保存现场堆栈信息

Looper比较适合在发布前进行测试或者小范围灰度测试然后定位问题,ChoreographerHelper适合监控线程环境的app的掉帧情况来计算app在某些场景的流畅度然后又针对性的做性能优化

image.png

Looper日志检测卡顿

Android主线程更新UI,如果界面1秒刷新至少60次,即FPS小于60,用户就会产生卡顿感觉,简单来说,Android使用消息机制进行UI更新,UI线程有个Looper,在其loop方法中会不断取出message,调用其绑定的Handler在UI线程执行,如果在handler的dispatchMessage方法里有耗时操作,就会发生卡顿

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYEemlQj' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片