zoukankan      html  css  js  c++  java
  • App启动速度优化

    一、概述

    要优化App的启动速度,首先需要了解App的启动流程。在Android系统中,系统会为每一个应用开辟一个Linux进程,默认情况下应用都运行在自己的进程中。

    一个完整的App启动流程也包含进程的创建过程,关于进程(Application),Google在解释文档中描述为:

    By default, every application runs in its own Linux process. Android starts the process when any of the application’s components need to be executed, then shuts down the process when it’s no longer needed or when the system must recover memory for other applications.

    也就是说:

    • 当用户要启动App中任意一个组件时,系统都会首先启动这个应用的进程
    • 在适当的时候,系统会关闭这个进程

    那么,当用户点击桌面图标启动一个应用界面时,底层的完整流程如下:

    1. Click事件
    2. Launcher调用startActivity()
    3. ActivityManagerService判断进程不存在,则启动进程,否则直接跳到最后一步
    4. Zygote进程Fork子进程ActivityThread,并返回进程id
    5. ActivityThread调用Looper.loop()开启消息循环
    6. ActivityThread加载Application类并绑定进程
    7. 实例化目标Activity并启动

    从上面的流程图可以得出

    • 如果App进程不存在,则需要执行3,4,5,6步,我们称之为“冷启动”,一般是首次启动,或者进程被杀死后;
    • 如果App进程存在,则直接实例化并启动目标Activity,我们称之为“温启动”,一般发生在应用退出后,进程被杀前;
    • 还有一种情况,如果进程和目标Activity都存在,只是切到后台,我们称之为“热启动”,如按了Home键。

     

    二、检测App启动速度

    测量App启动时间的方法很多,常用的有两种(以启动腾讯新闻为例):

    (1)过滤Displayed log

    启动App时,系统会打印相关log,一般tag为 "ActivityManager" 或 "ActivityTaskManager"

    01-25 15:12:19.006  1042  2934 I ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.tencent.news/.activity.SplashActivity bnds=[540,806][792,1146]} from uid 10089 ,pid=2941
    01-25 15:12:19.027  1042  3889 I ActivityTaskManager: The Process com.tencent.news Already Exists in BG. So sending its PID: 11291
    01-25 15:12:19.028  1042  3889 W ActivityTaskManager: Tried to set launchTime (0) < mLastActivityLaunchTime (16006291)
    01-25 15:12:19.165  1042  1179 I ActivityTaskManager: Displayed com.tencent.news/.activity.SplashActivity: +121ms

    从第二行可以看出,进程已存在于后台,所以此次启动是“温启动”,启动时间为121ms。

    我们在多任务中杀死该进程后再次启动:

    01-25 15:15:04.693  1042  3838 I ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.tencent.news/.activity.SplashActivity bnds=[540,806][792,1146]} from uid 10089 ,pid=2941
    01-25 15:15:05.233  1042  1179 I ActivityTaskManager: Displayed com.tencent.news/.activity.SplashActivity: +506ms

    此次启动为“冷启动”,耗时506ms。

    (2)命令行

    可以通过如下命令行检测启动时间:

    adb shell am start -W 包名/Activity名

    依然以腾讯新闻为例:

    $ adb shell am start -W   com.tencent.news/.activity.SplashActivity
    Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.tencent.news/.activity.SplashActivity }
    Status: ok
    LaunchState: WARM
    Activity: com.tencent.news/.activity.SplashActivity
    TotalTime: 93
    WaitTime: 106
    Complete

    通过“LaunchState:WARM”可知此次启动为“温启动”,耗时为96ms(WaitTime:106包含了前一个应用的onPause时间)。

    再次通过多任务杀死应用后启动:

    $ adb shell am start -W   com.tencent.news/.activity.SplashActivity
    Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.tencent.news/.activity.SplashActivity }
    Status: ok
    LaunchState: COLD
    Activity: com.tencent.news/.activity.SplashActivity
    TotalTime: 508
    WaitTime: 519
    Complete

    通过“LaunchState:COLD”可知此次启动时“冷启动”,耗时508ms。

    我们再试一下按Home键后启动:

    $ adb shell am start -W   com.tencent.news/.activity.SplashActivity
    Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.tencent.news/.activity.SplashActivity }
    Warning: Activity not started, its current task has been brought to the front
    Status: ok
    LaunchState: HOT
    Activity: com.tencent.news/.activity.SplashActivity
    TotalTime: 115
    WaitTime: 116
    Complete

    同样的,通过“LaunchState:HOT”可知此次启动为“热启动”,耗时115ms。


    三、App启动速度优化

    当App启动慢的时候,首先要判断是“温/热启动”慢,还是“冷启动”慢,如果只是“冷启动”慢,则判断是否是自定义的Application类初始化时执行了过多耗时的方法,可以通过TraceView工具来定位;如果不是Application类初始化的问题,那就可能是测试机型的问题,需要Framework层来解决。不过这种情况一般比较少,目前市面上的机型都是长期优化的结果。大多数启动慢都是App自己处理不当造成的。

    关于App启动速度优化主要有两个方面:

    • 减少耗时
    • 优化体验

    从App的启动流程可以知道,应用层能优化的地方只有Application和Activity初始化过程。首先,可以通过TraceView工具来定位耗时方法,然后具体问题具体分析。

    关于减少耗时的手段无外乎这几种:

    • 延迟加载 / 懒加载
    • 异步线程执行耗时操作,如图片加载、网络访问、IO操作等
    • ViewStub的使用
    • 减少布局层次和嵌套布局

    下面说一种市面上常用的优化体验的方法:placeholder UI。所谓placeholder UI就是通过添加一些占位图优化数据加载过程的等待体验。

    我们可以在等待第一帧的过程中,通过加入配置来增加体验。我们写一个简单demo,在Activity的onCreate方法中添加模拟耗时方法。

        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    for(int i=0;i<100000;i++) { Log.i("111","模拟初始化耗时!"); } }

    启动App时,会发现大概有1~2秒白屏时间,这就是我们需要优化体验的地方。

    下面我们为App添加一个主题Theme.MyApplication,并且设置window_background属性:

        <application
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/Theme.MyApplication">
        <style name="Theme.MyApplication" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
            <item name="android:windowBackground">@drawable/welcome_bg_1920</item>
        </style>

    再次启动App,发现白屏变成了我们设置的背景图,用户体验明显会好很多。

    但是这样会造成OverDraw,我们可以在Activity创建的时候去掉window_background:

    @Override
        protected void onCreate(Bundle savedInstanceState) {
            setTheme(R.style.Theme_MyApplication2);//去掉背景
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            for(int i=0;i<100000;i++){
                Log.i("111","模拟初始化耗时!");
            }
        }
        <style name="Theme.MyApplication2" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
            <item name="android:windowBackground">@android:color/transparent</item>
        </style>
    作者:观雪听涛
    本站所有原创内容基于知识共享-署名-非商业性使用4.0国际许可协议发布,欢迎转载引用,但必须保留署名和出处
  • 相关阅读:
    【面经】网易互娱一面
    【Go】简易到简陋的web服务器
    【Go】连接本地MySQL读取数据
    【MySQL】Windows10下安装
    【深入理解计算机系统】第十三章-并发编程
    【Python】数据库查询 & 批量下载文件
    【深入理解计算机系统】第十二章-网络编程
    grep的时候Binary file matches **.log 怎么解决
    高并发系统架构思想
    mysql 索引
  • 原文地址:https://www.cnblogs.com/not2/p/14326090.html
Copyright © 2011-2022 走看看