启动性能优化

一、应用启动慢的原因

1.在主线程执行了太多耗时的操作,比如加载数据,或者初始化三方库等等,导致在Application的oncreate或者Activity的oncreate方法中耗时太久
2.布局嵌套太深,或者一些不会立即使用的布局也在一开始一起加载到内存中

二、启动耗时统计

1.使用adb命令方式统计启动时间

adb shell amstart -S -W com.example.MainActivity

-S 表示杀掉当前进程然后重启该应用
-W 表示开启应用启动耗时日志
对应的打印如下:

Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.example.appstartdemo/.MainActivity }
Warning: Activity not started, its current task has been brought to the front
Status: ok
Activity: com.example.appstartdemo/.MainActivity
ThisTime: 67
TotalTime: 67
WaitTime: 87
Complete

2.直接查看系统日志,在对应的DisPlayed关键字中,会统计应用启动到首个Activity绘制到屏幕上的时间,如下打印:

ActivityManager: Displayed com.example.appstartdemo/.MainActivity: +401ms

三、启动耗时分析

使用Android Studio自带的Profile,通过配置Profile的configuration,选择Trace Java Methods,Run 的时候选择Profile “app”,就可以生成一段时间内的方法调用栈记录文件。配置形式如下:
在这里插入图片描述

我们通常可以用如下几种方式去打开这个Record文件:

1.火焰图(Frame Chart)方式

它会把相同的调用栈合并,然后根据执行的时间占比,生成一个个柱状图形,总体像火焰的样子。如下:
在这里插入图片描述
X轴:方法调用的时间占比,或者更精确地叫抽样数,即X轴越宽,则被抽中采样的次数越多,方法所消耗的时间就越长。
Y轴:表示调用栈,方法的调用链是由下而上的,每一个Y值都表示一个方法。
因此越在底部的方法,占用的时间就越多,因为这是方法的总入口。
柱子越高,说明调用链越深。
我们应该着重关注“平顶山”的情况,它表示柱子顶部X轴占比比较大,花费的时间比较长,这是消耗CPU的关键所在。

2.Top Down方式

显示一个调用链表中各个方法的具体执行耗时的时间值(微妙μs = 1000/1ms = 百万分之一秒),显示效果如下:
在这里插入图片描述
Total:表示该方法执行总体的耗时
Self:执行该方法本身的代码耗时,不包含子函数
Children:子函数的耗时
通过Top Down查看调用链,可以去分析耗时比较多的方法,然后去重点关注和优化。

四、启动性能优化方法

1.黑白屏的优化

由于冷启动一个新的应用,会存在一定的耗时,Google为了避免让程序看起来有延迟的情况出现,即用户点击图标后就会有即时的响应,会在App创建的过程中先显示一个空白页作为过渡。根据主题的不同,就会出现黑屏或者白屏时间比较长的情况,这是大部分用户无法容忍的,需要做优化。
优化的推荐方法是,首先自定义一个主题,继承当前的主题,然后设置它的windowbackground属性为一张跟业务相关的图片,也就是我们常见的欢迎界面,如下:

# 创建新的主题
<resources>

    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    </style>

    <style name="MyTheme" parent="AppTheme">
        <item name="android:windowFullscreen">true</item>
        <item name="android:windowBackground">@drawable/launch_bg</item>
    </style>

</resources>

然后在manifest文件中设置该主题:

# 在清单文件中给Activity设置主题
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.appstartdemo">

    <application
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:theme="@style/MyTheme">
        </activity>
    </application>

</manifest>

设置了windowbackground属性后,那么图片会一直存在;在启动完Activity之后,需要把主题重新设置回默认主题,避免背景图还一直存在。

# Activity启动后,设置回默认的主题
public class MainActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // 模拟耗时操作,显示更加的明显
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        setTheme(R.style.AppTheme);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }
}
2.主线程的耗时优化

2.1避免在Application的oncreate方法或者Activity的oncreate方法中,去做过多的耗时操作,比如数据加载、网络请求、第三方库的初始化等等
2.2使用idleHandler去做耗时的数据加载和网络请求、三方库的初始化
2.3使用懒加载,只有在用到的时候,才去加载数据

3.布局优化

3.1使用include标签,去包含可以重复使用的布局,减少XML代码的冗余
3.2使用merge标签去作为被include的子布局文件的顶层布局,这样在被合并到主布局之后,就可以减少一层布局的嵌套
3.3使用ViewStub标签来引入一个子布局文件,最开始是不可见的,尺寸大小为0的控件。在启动Activity加载布局的时候,并不会把ViewStub的内容加载到View树里面,只有在对ViewStub执行setvisibility或者inflate的时候,才会去真正加载布局。这相当于是View的一种懒加载,对提高启动性能很有帮助。
对于那些最开始并不会用到的子View,或者那些一开始就设置gone的子View,适合使用ViewStub。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值