Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Android性能优化之启动速度优化

Android性能优化之启动速度优化

作者头像
用户1155943
修改于 2018-01-14 10:58:21
修改于 2018-01-14 10:58:21
1.8K0
举报
文章被收录于专栏:Android点滴积累Android点滴积累

Android性能优化之启动速度优化

  Android app 启动速度优化,首先谈谈为什么会走到优化这一步,如果一开始创建 app 项目的时候就把这个启动速度考虑进去,那么肯定就不需要重新再来优化一遍了。这是因为在移动互联网时代,大家都追求快,什么功能都是先做出来再说,其他的可以先不考虑,先占据先机,或者验证是否值得做。那为什么要这么做呢?我个人的观点有以下几点

  • 如果 app 不能快速开发出来,先放出去验证一下可行性,可能连是否值得做都不知道,如果花很长时间做了一个对用户无价值的功能,那么还不如不做
  • 如果 app 不能快速做出来,可能被竞争对手捕获先机,那么可能错失最佳商业时机
  • 如果一开始就规定不能影响启动速度的这个目标,那么做功能的时候就会有束缚,快不起来
  • app 初期大家都忙着开发新功能,迭代新版本,没有时间停下来做优化
  • 同类型 app 变多,竞争对手变多,大家才开始关注启动性能,才开始做启动速度优化(有主动出击也有被动优化)

一、引起性能问题的原因

  随着项目不断的快速迭代,往往会造成App启动卡慢现象,因为可能在App主进程启动阶段或者在主界面启动阶段放了很多初始化其他业务的逻辑,而这些业务落地可能一开始并不需要用到。本文从作者的亲身经历给大家阐述启动速度优化相关的点点滴滴,为启动速度优化提供一种思路给大家参考。

二、为什么要做启动速度优化

  App启动卡慢会影响一个App的卸载率和使用率。启动速度快会给人一种轻快的感觉,减少用户等待时间。如果一个App从点击桌面图标到看到主界面花了10秒,请问你能接受么?忍耐不好的估计直接就卸载了,或者没等打开就直接Home键按出去,然后杀进程了。这样一来App卸载率提升了,使用率下降了。所以对于有大量用户的App来说,这些性能细节是很重要的,毕竟用户就是钱啊。

三、分析制定优化技术路线

3.1 分析启动性能瓶颈

  在具体的优化之前,首先我们得找到需要优化的地方,怎么找?这就要求了解Android App的启动原理,我们要知道一个App从点击桌面图标到我们看到App的主界面整个过程中经过了哪些步骤,哪些地方是我们可以优化的地方。下图是App启动过程的一个大概描述。

具体的代码流程,分析关键的函数耗时

  图中onFirstDrawFinish和onWindowFocusChanged的前后顺序可能会颠倒,但是时间差不大。

3.2 制定优化方向

  从上面的分析可以看出,App启动过程中我们优化的地方包括主进程启动流程和主界面启动流程,主进程启动就是Application的创建过程,主界面启动就是MainActivity的创建过程。只需要分别对这两个部分进行优化即可。

  1. Application中attachBaseContext最早被调用,随后是onCreate方法,尽量在这两个方法中不要有耗时操作。
  2. MainActivity中重点关注onCreate,onResume,onWindowFocusChange,Activity启动完成结束标志这里采用没有使用生命周期函数,而是以主界面View的第一次绘制作为启动完成的标志,View被第一次绘制证明View即将展示出来被我们看到。所以我们在Activity根布局中加入一个自定义View,以它的onDraw方法第一次回调作为Activity启动完成的标志。
代码语言:java
AI代码解释
复制
public class FirstDrawListenView extends View {     
	private boolean isFirstDrawFinish = false;      
	private IFirstDrawListener mIFirstDrawListener;      
	
	public FirstDrawListenView(Context context, AttributeSet attrs) {         
		super(context, attrs);     
	}      
	
	@Override     
	protected void onDraw(Canvas canvas) {         
		super.onDraw(canvas);         
		if (!isFirstDrawFinish) {             
			isFirstDrawFinish = true;             
			if (mIFirstDrawListener != null) {                 
				mIFirstDrawListener.onFirstDrawFinish();             
			}         
		}     
	}      
	
	public void setFirstDrawListener(IFirstDrawListener firstDrawListener) {         
		mIFirstDrawListener = firstDrawListener;     
	}      
	
	public interface IFirstDrawListener {         
		void onFirstDrawFinish();     
	} 
}

四、怎么统计数据查看优化前后的数据对比

  通过上面的分析,我们可以统计进程启动各个阶段的耗时点,以及Activity启动各个阶段的耗时点(这个步骤需要额外在主布局中加入一个自定义的空View,监听它的onDraw方法的第一次回调),可以通过埋点数据收集这些数据,在优化之前可以先加入埋点数据,统计上报各个时间段的埋点,所以需要先发个版本验证一下优化之前的情况。统计数据的机制加入之后,就可以着手优化了,一边优化一边对比,可以很清楚看到优化前后的对比。

五、制定优化的目标

  由于App启动速度在不同是设备上差别很大,所以目标不太好定,但是做事情总得要有个目标吧。首先我们使用大家都熟悉的一个概念“秒开”,其次是冷启动热启动分开算,再次是分出不同的机型(高端机,中端机型,低端机型),最后是需要先看看没优化之前的启动数据。这样就可以定义出类似下面的目标:

  1. 高端机型1秒内打开(比如小米5,Android6.0以上)
  2. 中端机型1.5秒内打开
  3. 低端机型2.5秒内打开

  上面是终极目标,真正优化的时候,要结合App实际数据以及团队实际情况来定自己的优化目标。

六、优化具体步骤

  一般来说,快速优化最好的方式就是把不必要提前做的操作放到异步线程中去做,也就是我们经常做的异步加载。除了异步加载,一些真正有性能影响的代码需要做具体优化。下面依次介绍一些具体的优化实施步骤。

6.1 封装一个打印耗时点日志的辅助类

  优化的时候为了快速定位耗时的代码块,我们需要在耗时代码块的前后加上日志,统计耗时具体的时间。这个能在Debug模式下帮助我们快速分析定位到耗时的代码块,然后我们在针对具体的耗时代码块去下手,看看怎么优化。

6.2 异步加载一:Application中加入异步线程

  在Application中封装两个方法:onSyncLoad(同步加载)和 onAsyncLoad(异步加载,在Thread中执行),把不需要同步加载的部分全部放到onAsyncLoad方法,需要同步的方法放到onSyncLoad中去做,就这种简单的分类就可以带来一个很好的优化效果。

代码语言:java
AI代码解释
复制
public class StartUpApplication extends Application {

    @Override
    public void onCreate() {
        // 程序创建时调用,次方法应该执行应该尽量快,否则会拖慢整个app的启动速度
        super.onCreate();
        onSyncLoadForCreate();
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        onSyncLoad();
        onAsyncLoad();
    }

    private void onSyncLoadForCreate() {
        AppStartUpTimeLog.isColdStart = true;   // 设置为冷启动标志
        AppLog.log("StartUpApplication onCreate");
        AppStartUpTimeLog.logTimeDiff("App onCreate start", false, true);
        BlockingUtil.simulateBlocking(500); // 模拟阻塞100毫秒
        AppStartUpTimeLog.logTimeDiff("App onCreate end");
    }

    private void onSyncLoad() {
        AppLog.log("StartUpApplication attachBaseContext");
        AppStartUpTimeLog.markStartTime("App attachBaseContext", true);
        BlockingUtil.simulateBlocking(200); // 模拟阻塞100毫秒
        AppStartUpTimeLog.logTimeDiff("App attachBaseContext end", true);
    }

    public void onAsyncLoad() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 异步加载逻辑
            }
        }, "ApplicationAsyncLoad").start();
    }
}

6.3 异步加载二:MainActivity中加入异步线程

  这一步骤与Application的优化思路一样,也是封装onSyncLoad和onAsyncLoad方法对现有代码进行一个分类,但是这两个方法的调用时机要晚一点,是在主界面首屏绘制完成的时候调用。这个步骤也需要new一个Thead,属于额外的开销,不过这不影响我们整体性能。

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

  还有些操作必须要在UI线程做,但是不需要那么快速就做,这里放到首屏绘制完成之后,我们之前在主布局中加入一个空的View来监听它的第一次onDraw回调,我们通过接口的方式把这个事件接到我们的MainActivity中去(Activity中实现接口的onFirstDrawFinish方法)。为了让用户尽快看到主界面,我们就可以把一些需要在UI线程执行,但是又不需要那么快的执行的操作放到onFirstDrawFinish中去。

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

  把主界面中不需要第一次就用到的布局全部使用动态加载的方式来处理,使用ViewStub或者直接在使用时动态addView的方式。

6.6 主布局文件深度优化

  如果做了上面这些优化还是会发现进入主界面还是有些慢,那么需要重点关注主布局文件了。主布局文件的复杂度直接影响到了Activity的加载速度,这个时候需要对主布局文件进行深度优化了。Activity在加载布局的时候,会对整个布局文件进行解析,测量(measure),布局(layout)和绘制(draw),所以设计简单合理的布局尤为重要。布局的优化不做详细介绍,网上很多文章的。几个重要的优化如下:

  1. 减少布局层级
  2. 减少首次加载View的数量
  3. 减少过度绘制

  如果需要看看主布局加载具体用了多少时间,需要用自定ViewGroup作为根布局根元素,然后监控它的onInflateFinished,onMeasure,onLayout,onDraw方法,通过我们之前写好的打印时间日志的辅助类,打印一些关键日志,可以分析出具体的耗时的步骤,还可以定位哪个View加载耗时最长。

6.7 功能代码深度优化

  前面的优化步骤中,我们有部分耗时操作放到了首屏绘制onFirstDrawFinish之后来做了,这里会带来一个体验上的问题,虽然进入主界面变快了,但是可能进入之后短暂的时间类UI线程是阻塞的,如果有其他的UI操作可能会卡主,因为onFirstDrawFinish中挂了很多耗时的操作,需要等这些做完之后UI线程才能空闲。所以我们还需要对一些功能代码进行优化,确保其真正用时少。另外我们异步加载线程中的操作是有一定的安全风险的,如果有些操作很耗时,可能导致我们进入主界面需要用到数据时还没有准备好,所以异步加载我们要注意代码块的顺序,如果有些非常耗时的操作考虑用单独的线程去处理。

七、总结

  优化是一条持续之路,通过优化我们可以了解到影响启动性能的因素有哪些,这样我们平时在编码的过程中就会多注意自己的代码性能。本文从全局的角度去看待整个启动性能优化,看起来好像还挺容易,但是可能实际过程中优化并不会很顺利,不同的设备上可能表现不一样,有时候可能启动一个服务都会耗时。所以要想真正的不耗时,那就是大招:删除它吧。

八、项目地址

模拟耗时点,打印日志观察生命周期函数回调情况

https://github.com/PopFisher/AppStartUpSpeedOpt

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-10-24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
关于Android性能优化的几点建议
由于Android应用的沙箱机制,每个应用所分配的内存大小是有限度的,内存太低就会触发LMK(Low Memory Killer)机制,进而会出现闪退现象。如果要对内存进行优化,就需要先搞懂java的内存是如何分配和回收的,关于这方面,可以重点参考下面的内容: Java 垃圾回收器的GC机制,看这一篇就够了 Android 内存泄漏常见案例及分析 Android应用内存泄漏的定位、分析与解决策略
Android技术干货分享
2019/07/03
9030
关于Android性能优化的几点建议
深入研究Android启动速度优化(上)- 看完这些启动优化已经完成80%了
启动是指用户从点击 icon 到看到页面首帧的整个过程,启动优化的目标就是减少这一过程的耗时。启动性能是 APP 使用体验的门面,启动过程耗时较长很可能导致用户使用 APP 的兴趣骤减。提高启动速度是每一个 APP 在体验优化方向上必须要做的关键技术突破。
Rouse
2024/05/09
1.9K0
深入研究Android启动速度优化(上)- 看完这些启动优化已经完成80%了
Android性能优化:一份详细的布局优化实战指南,太特么重要了
对于Android开发者来说,懂得基本的应用开发技能往往是不够,因为不管是工作还是面试,都需要开发者懂得大量的性能优化,这对提升应用的体验是非常重要的。对于Android开发来说,性能优化主要围绕如下方面展开:启动优化、渲染优化、内存优化、网络优化、卡顿检测与优化、耗电优化、安装包体积优化、安全问题等。 下面是我整理了网上很多大佬的经验分享对Android性能优化做了一个总结。
用户9227784
2021/12/20
9380
❤️Android 性能优化之启动优化❤️
用户希望应用能够快速打开。启动时间过长的应用不能满足这个期望,并且可能会令用户失望。轻则鄙视你,重则直接卸载你的应用。
Android 帅次
2021/11/12
9400
❤️Android 性能优化之启动优化❤️
深入研究Android启动速度优化(下)- 不敢说100%秒开,但这样做“雀食”是快
在上一篇文章《深入研究Android启动速度优化(上)- 看完这些启动优化已经完成80%了》中,梳理了应用启动的整个过程和问题,启动优化阶段与指标是什么,启动耗时方法的数据统计八种工具与分析,以及一些常见的启动时间问题。可以说是完成了启动优化工作最难的一部分。
Rouse
2024/05/10
2.8K0
深入研究Android启动速度优化(下)- 不敢说100%秒开,但这样做“雀食”是快
Android性能优化(一)之启动加速35%
随着项目版本的迭代,App的性能问题会逐渐暴露出来,而好的用户体验与性能表现紧密相关,从本篇文章开始,我将开启一个Android应用性能优化的专题,从理论到实战,从入门到深挖,手把手将性能优化实践到项目中,欢迎持续关注!
用户2898788
2018/08/21
2K0
Android性能优化(一)之启动加速35%
Android性能优化(一)—— 启动优化,冷启动,热启动,温启动
App启动方式分三种:冷启动(cold start)、热启动(hot start)、温启动(warm start)
233333
2024/06/28
3450
Android性能优化(一)—— 启动优化,冷启动,热启动,温启动
Android性能优化(一)
一个应用App的启动速度能够影响用户的首次体验,启动速度较慢(感官上)的应用可能导致用户再次开启App的意图下降,或者卸载放弃该应用程序。
xiangzhihong
2021/01/22
2.7K0
Android性能优化,一对一直播源码启动速度优化之耗时检测处理
一对一直播源码的启动速度缓慢这是很多开发者都遇到的一个问题,比如启动缓慢导致的黑屏,白屏问题,大部分的答案都是做一个透明的主题,或者是做一个Splash界面,但是这并没有从根本上解决这个问题。那么如何从根本上解决这个问题或者做到一定程度的缓解?
云豹科技程序员
2021/06/24
5070
Android性能优化来龙去脉总结
一款app除了要有令人惊叹的功能和令人发指交互之外,在性能上也应该追求丝滑的要求,这样才能更好地提高用户体验。
用户1263954
2018/07/30
3380
Android性能优化来龙去脉总结
Android性能优化
讲到Android开发,就不得不谈一下Android的优化,不管是平时开发中我们需要注意的一些Android对Java的一些类的优化,还是实际开发中对性能的优化,其实早在15年的google全球大会上google就Android的性能优化就给我们做了很好的介绍:点击打开链接。 接下来本文从几个方面入手讲一讲Android 的优化,主要从以下几点:布局优化,绘制优化,内存优化,响应速度优化,bitmap优化(主要结合listview),线程优化,其他常用性能优化;内存检测工具mat分析与提高。 为了达到优化的
xiangzhihong
2018/02/05
1.1K0
Android性能优化
Android性能优化笔记(一)——启动优化
从上面的总结可以看出,在应用的启动过程中,冷启动是最慢最耗时的,系统以及应用本身都有大量的工作需要处理,所以,冷启动对于应用的启动速度是最具挑战以及最有必要进行优化的。
分你一些日落
2021/12/13
1K0
Android性能优化系列之渲染优化
众所周知的Android系统每隔16ms重新绘制一次activity,也就是说你的app必须在16ms内完成屏幕刷新的所有逻辑操作,这样才能达到60帧/s。而用户一般所看到的卡顿是由于Android的渲染性能造成的。 本篇博客将介绍Android的渲染相关知识。
老马的编程之旅
2022/06/22
1K0
Android性能优化系列之渲染优化
Android 性能优化最佳实践
快,稳,省,小,这四点很形象的代表了性能的四个方面,同时也让我们知道我们 App 现在是否是款性能良好的 APP,如果有一项不达标,那么说明我们的应用有待优化。
李林LiLin
2020/11/22
1.4K0
Android 启动优化详解
Dex文件用的到的类和安装包APK里面各种资源文件一般都比较小,但是读取非常频繁。
ruochen
2021/12/15
5.4K0
你想要的Android性能优化系列:启动优化 !
手机桌面点击一个应用,用户希望应用能 及时响应、快速加载。启动时间过长的应用可能会令用户失望。这种糟糕的体验可能会导致用户在 Play 商店针对您的应用给出很低的评分,甚至完全弃用您的应用。
胡飞洋
2020/07/23
1.7K0
Android App性能优化全方面解析
为了让各位读者过好本次国庆节和中秋节,假日期间我将会推送一些非技术类文章,让你的假日不在孤单迷茫!
开发者技术前线
2020/11/23
6970
Android App性能优化全方面解析
Android性能优化典范 - 第6季
导语 这里是Android性能优化典范第6季的课程学习笔记,从被@知会到有连载更新,这篇学习笔记就一直被惦记着,现在学习记录分享一下,请多多指教包涵!这次一共才6个小段落,涉及的内容主要有:程序启动时间性能优化的三个方面:优化activity的创建过程,优化application对象的启动过程,正确使用启动显屏达到优化程序启动性能的目的。另外还介绍了减少安装包大小的checklist以及如何使用VectorDrawable来减少安装包的大小。 1. App Launch time 101 提高程序的启动速度
腾讯Bugly
2023/04/02
7260
Android性能优化典范 - 第6季
Android性能优化方案
大家肯定都知道Android中有许多布局,比如Linerlayout、RelativeLayout等,布局优化就是减少布局文件层级,层级减少了,那么程序绘制时就快了许多,所以可以提高性能。
黄林晴
2019/01/10
7400
Android 性能优化—— 启动优化提升60%
一个应用App的启动速度能够影响用户的首次体验,启动速度较慢(感官上)的应用可能导致用户再次开启App的意图下降,或者卸载放弃该应用程序
Android技术干货分享
2019/07/08
2K0
推荐阅读
相关推荐
关于Android性能优化的几点建议
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档