Android性能优化(一)App启动时间的优化

一:App启动方式

1、冷启动:当启动应用时,后台没有该应用的进程,系统要重新创建一个新的进程分配给该应用,这种启动方式就是冷启动。冷启动首先会为应用创建一个新进程,然后先后创建和初始化Application与启动Activity,最后将界面显示出来。

2、热启动:当启动应用时,后台已经存在该应用的进程(比如:按Home键、Back键的时候,应用虽然退出了前台,但后台依然保存着应用的进程),这种情况下,会直接从已有的进程中启动应用,这种叫做热启动。热启动会直接将应用从后台拉起,不走App进程、Application、Activity的创建和初始化这几步,而是直接将应用显示在前台。 

二:App启动流程

从App启动方式来看,冷启动最缓慢,App本身的工作要从头开始,下面是App冷启动的流程:

1.加载启动App

2.启动后立即显示出一个空白的Window,就是我们常见的白屏或黑屏

3.创建APP进程

4.创建App主线程

5.创建Application对象

6.创建启动Activity对象

7.View绘制,第一次显示屏幕

上面的步骤1到4是启动App固有的系统流程,不是我们能控制的,所以也不在优化的考虑范围内。可以优化的空间就是Application和启动Activity的创建和初始化

Google给我们的启动加速的方向是:

1.替换提前展示的空白Window界面,给用户一个快速打开APP的感觉

2.避免在启动时做密集沉重的初始化工作

3.定位问题:避免I/O操作、反序列化、网络操作、布局嵌套等

接下来我们就从这个几方面去讲解一下App启动优化的方法:

三:启动之主题替换

通常我们打开一个App的时候都是立即就展示出一个欢迎界面之类的,而不是白屏或者黑屏,其实这是对启动界面的主题进行了替换而已。

在我们的styles文件中自定义一个样式Launcher,放置一张背景图,如下

    

在windowBackground中放置一个背景图,当然我还设置了其他属性使图片全屏显示,然后将样式设置给启动Activity

        
            
                

                
            
        

这样启动时候就可以立即展示你所设置的背景图了,如果你想要在启动Activity中显示回原来的主题,可以在启动Activity中这样设置

@Override
    protected void onCreate(Bundle savedInstanceState) {
        //替换为原来的主题,在onCreate之前调用
        setTheme(R.style.AppTheme);
        super.onCreate(savedInstanceState);
    }

四:启动时间计算

在cmd中输入adb shell am start -W [包名]/[全类名],即通过adb启动我们的Activity,控制台会输出我们的启动时间

Android性能优化(一)App启动时间的优化_第1张图片

主要关注ThisTime、TotalTime和WaitTime三个数据,那么这三个时间分别代表什么呢?

1.ThisTime:所有启动Activity中最后那个Activity的启动耗时

2.TotalTime:所有Activity的启动耗时,因为例子中,整个启动过程中就启动SplashActivity这个Activity,所以ThisTime和TotalTime相等
3.WaitTime:从AMS启动App到Activity的总时间,在启动一个Activity之前会先调用当前activity的onPause,然后通过AMS去启动后面的步骤。所以说这个WaitTime就包括了当前Activity的onPause时间。

从前面我们知道,App启动时间的优化我们重点关注的是Application和第一个显示Activity的初始化操作,一般来说项目都会在Application的onCreate方法中做一些全局的初始化,所以下一步去看看Application中做了一些什么初始化操作。

五:App启动的优化

这是我的Application中的初始化操作

        //EventBus初始化
        EventBus.getDefault().register(this);
        // 在使用 SDK 各组间之前初始化 context 信息,传入 ApplicationContext
        SDKInitializer.initialize(this);
        //自4.3.0起,百度地图SDK所有接口均支持百度坐标和国测局坐标,用此方法设置您使用的坐标类型.
        //包括BD09LL和GCJ02两种坐标,默认是BD09LL坐标。
        SDKInitializer.setCoordType(CoordType.BD09LL);
        //初始化友盟
        initUm();
        //初始化路由相关
        initRouter(this);
        //初始化日志收集
        initCrashReport();
        //初始化http
        initRxHttp();

现在我想统计上面这些方法的执行耗时,我们知道在代码之间插入Debug.startMethodTracing(filename)和Debug.stopMethodTracing()可以追踪所包含代码的执行耗时,这些数据会写入一个.trace文件中,只要导出这个文件就可以看到详细信息了

                   
          
//开始代码追踪,参数是trace文件保存在手机的全路径名  
Debug.startMethodTracing(this.getExternalFilesDir(Environment.MEDIA_MOUNTED).getPath() + "01");
        
        //EventBus初始化
        EventBus.getDefault().register(this);
        // 在使用 SDK 各组间之前初始化 context 信息,传入 ApplicationContext
        SDKInitializer.initialize(this);
        //自4.3.0起,百度地图SDK所有接口均支持百度坐标和国测局坐标,用此方法设置您使用的坐标类型.
        //包括BD09LL和GCJ02两种坐标,默认是BD09LL坐标。
        SDKInitializer.setCoordType(CoordType.BD09LL);
        //初始化友盟
        initUm();
        //初始化路由相关
        initRouter(this);
        //初始化日志收集
        initCrashReport();
        //初始化http
        initRxHttp();
        //结束代码追踪
        Debug.stopMethodTracing();

执行以上代码,然后通过将在cmd中输入adb pull [trace文件保存在手机的全路径名] 导出trace文件到电脑中,再通过Android Studio打开文件

Android性能优化(一)App启动时间的优化_第2张图片

从图中可以看到代码中每个方法的执行时间和占用时间的百分比,initRouter时间占比55.6%、initUm占比20.1%、SDKInitializer.initialize占比19.5%,主要是这个三个初始化占用了大多数时间,它们分别是路由框架ARouter的初始化,友盟的初始化,百度地图的初始化。

一些常用的优化思路:

  • 考虑异步初始化第三方组件,不阻塞主线程
  • 延迟第三方的初始化时间,因为异步初始化有可能遇到初始化还没完成主线程已经用到的情况,这种情况可以考虑延时到第三方组件使用之前进行初始化
  • 数据库、IO操作、网络请求尽量不要在Application中执行,能异步初始化的就尽量异步,如果不能异步初始化就尽量延时,不要在Application中创建线程池。
  • 在首页Activity中,布局尽量减少嵌套,在onCreate、onStart、onResume方法中尽量避免耗时操作

因为首页activity要用到组件ARouter,所以我考虑把它的初始化延时到SplashActivity中的使用前,经测试,百度地图不能在子线程初始化,所以考虑延时,然后友盟初始化放在子线程中

    private void initOnWorkThread() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                //将线程设置为后台,避免和主线程争抢资源
                Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND);
                initUm();
                initCrashReport();
            }
        }).start();
    }


        //延迟在SplashActivity中初始化,界面完成以后才执行run方法,让界面先显示出来
        findViewById(R.id.splash_view).post(new Runnable() {
            @Override
            public void run() {
                //初始化ARouter
                ARouter.init(ComApplication.getInstance());
                // 在使用 SDK 各组间之前初始化 context 信息,传入 ApplicationContext
                SDKInitializer.initialize(ComApplication.getInstance());
                //自4.3.0起,百度地图SDK所有接口均支持百度坐标和国测局坐标,用此方法设置您使用的坐标类型.
                //包括BD09LL和GCJ02两种坐标,默认是BD09LL坐标。
                SDKInitializer.setCoordType(CoordType.BD09LL);

            }
        });

来看一下优化以后的启动时间

Android性能优化(一)App启动时间的优化_第3张图片

六:优化前后对比

优化前时间  优化后时间  时间相差  提升百分比
1560        1009     551   35.3%

优化启动速度提升了35.3%,这个效果还是比较满意的。

好了,上面就是我对App启动时间优化的总结和实践!

 

你可能感兴趣的:(Android,Android性能优化)