Android 性能优化(一) 之启动优化提升35%

初始启动加速

来看一下Google官方文档《Launch-Time Performance》 对应用启动优化的概述;
应用的启动分为冷启动、热启动、温启动,而启动最慢、挑战最大的就是冷启动:系统和App本身都有更多的工作要从头开始!
应用在冷启动之前,要执行三个任务:

1.加载启动App;

2.App启动之后立即展示出一个空白的Window;

3.创建App的进程;

而这三个任务执行完毕之后会马上执行以下任务:

创建App对象;

启动Main Thread;

创建启动的Activity对象;

加载View;

布置屏幕;

进行第一次绘制;

而一旦App进程完成了第一次绘制,系统进程就会用Main Activity替换已经展示的Background Window,此时用户就可以使用App了。
在这里插入图片描述
作为普通应用,App进程的创建等环节我们是无法主动控制的,只能用主题优化.可以代码优化的也就是Application、Activity创建以及回调等过程。
同样,Google也给出了启动加速的方向:

1. 利用提前展示出来的Window,快速展示出来一个界面,给用户快速反馈的体验;
2. 避免在启动时做密集沉重的初始化(Heavy app initialization);
3. 定位问题:避免I/O操作、反序列化、网络操作、布局嵌套等。

备注:方向1属于治标不治本,只是表面上快;方向2、3可以真实的加快启动速度。
接下来我们就在项目中实际应用。

启动主题优化

冷启动阶段 :

加载并启动应用程序。
启动后立即显示应用程序空白的启动窗口。
创建应用程序进程。
所谓的主题优化,就是应用程序在冷启动的时候(1~2阶段),设置启动窗口的主题。

因为现在 App 应用启动都会先进入一个闪屏页(LaunchActivity) 来展示应用信息。

1.默认情况

如果我们对App没有做处理(设置了默认主题),并且在 Application 初始化了其它第三方的服务(假设需要加载2000ms)
###### 1.默认情况
系统默认会在启动应用程序的时候 启动空白窗口 ,直到 App 应用程序的入口 Activity 创建成功,视图绘制完毕。( 大概是onWindowFocusChanged方法回调的时候 )

2.启动页设置系统默认背景为null,再加延时启动
    <item name="android:windowBackground">@null</item>  //系统背景为空,这样少绘制一层系统背景
    <item name="android:windowDisablePreview">true</item>  //启动页自动延时加载 

这个是仿照QQ实现的

3.设置闪屏图片主题

为了更顺滑无缝衔接我们的闪屏页,可以在启动 Activity 的 Theme中设置闪屏页图片,这样启动窗口的图片就会是闪屏页图片,而不是白屏。

    <item name="android:windowBackground">@drawable/lunch</item>  //闪屏页图片
    <item name="android:windowDrawsSystemBarBackgrounds">false</item><!--显示虚拟按键,并腾出空间-->

这样设置的话,就会在冷启动的时候,展示闪屏页的图片,作为广告.等App进程初始化加载入口 Activity (也是闪屏页) 就可以无缝衔接。

其实这种方式并没有真正的加速应用进程的启动速度,而只是通过用户视觉效果带来的优化体验。

代码优化

当然上面使用设置主题的方式优化用户体验效果治标不治本,关键还在于对代码的优化。

首先我们可以统计一下应用冷启动的时间。

使用traceview

根据上面启动时间的输出统计,我们就可以先记录优化前的冷启动耗时,然后再对比优化之后的启动时间。

Application 优化

Application 作为 应用程序的整个初始化配置入口,时常担负着它不应该有的负担~

有很多第三方组件(包括App应用本身)都在 Application 中抢占先机,完成初始化操作。

但是在 Application 中完成繁重的初始化操作和复杂的逻辑就会影响到应用的启动性能

通常,有机会优化这些工作以实现性能改进,这些常见问题包括:

  • 复杂繁琐的布局初始化
  • 阻塞主线程 UI 绘制的操作,
  • 如 I/O 读写或者是网络访问.
  • Bitmap 大图片或者 VectorDrawable加载
  • 其它占用主线程的操作

我们可以根据这些组件的轻重缓急之分,对初始化做一下分类 :

  1. 必要的组件一定要在主线程中立即初始化(入口 Activity 可能立即会用到)
  2. 组件一定要在主线程中初始化,但是可以延迟初始化。
  3. 组件可以在子线程中初始化。
  4. 放在子线程的组件初始化建议延迟初始化 ,这样就可以了解是否会对项目造成影响!

所以对于上面的分析,我们可以在项目中 Application 的加载组件进行如下优化 :

  • 将Bugly,x5内核初始化,SP的读写,友盟等组件放到子线程中初始化。(子线程初始化不能影响到组件的使用)

     new Thread(new Runnable() {
            @Override
            public void run() {
                //设置线程的优先级,不与主线程抢资源
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
      		//子线程初始化第三方组件
      		Thread.sleep(5000);//建议延迟初始化,可以发现是否影响其它功能,或者是崩溃!
            }
        }).start();
    
  • 将需要在主线程中初始化但是可以不用立即完成的动作延迟加载(原本是想在入口 Activity 中进行此项操作,不过组件的初始化放在Application 中统一管理为妙.)

handler.postDelayed(new Runnable() {
@Override
public void run() {
//延迟初始化组件
}
}, 3000);

闪屏页业务优化

最后还剩下那些为数不多的组件在主线程初始化动作,例如埋点,点击流,数据库初始化等,不过这些消耗的时间可以在其它地方相抵。

需求背景 : 应用App通常会设置一个固定的闪屏页展示时间,例如2000ms,所以我们可以根据用户手机的运行速度,对展示时间做出调整,但是总时间仍然为 2000ms。

闪屏页政展示总时间 = 组件初始化时间 + 剩余展示时间。

也就是2000ms的总时间,组件初始化了800ms,那么就再展示1200ms即可。

我们先了解一下 Application的启动过程,图片摘自 : 如何统计Android App启动时间
虽然这个以下图片的源码并不是最新源码(5.0源码),不过不影响整体流程。(7.0,8.0方法名会有所改变)。
在这里插入图片描述

在这里插入图片描述

冷启动的过程中系统会初始化应用程序进程,创建Application等任务,这时候会展示一个 启动窗口 Starting Window,上面分析了过,如果没有优化主题的话,那么就是白屏。

如果要了解更多启动过程源码,可以看博客 :Launcher 启动 Activity 的工作过程
分析源码后,我们可以知道 Application 初始化后会调用 attachBaseContext() 方法,再调用 Application 的 onCreate(),再到入口 Activity的创建和执行 onCreate() 方法。所以我们就可以在 Application 中记录启动时间。

//Application

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
		SPUtil.putLong("application_attach_time", System.currentTimeMillis());//记录Application初始化时间
    }

有了启动时间,我们得知道入口的 Acitivty 显示给用户的时间(View绘制完毕),在博客( View的工作流程)中了解到,在onWindowFocusChanged()的回调时机中表示可以获取用户的触摸时间和View的流程绘制完毕,所以我们可以在这个方法里记录显示时间。

//入口Activity

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
  
          long appAttachTime = SPUtil.getLong("application_attach_time");
          long diffTime = System.currentTimeMillis() - appAttachTime;//从application到入口Acitity的时间
 
		 //所以闪屏页展示的时间为 2000ms - diffTime.
    }

所以我们就可以动态的设置应用闪屏的显示时间,尽量让每一部手机展示的时间一致,这样就不会让手机配置较低的用户感觉漫长难熬的闪屏页时间(例如初始化了2000ms,又要展示2000ms的闪屏页时间.),优化用户体验。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值