美文网首页
Android性能优化——启动优化

Android性能优化——启动优化

作者: Juslt | 来源:发表于2019-05-25 13:54 被阅读0次

    一、前言

    APP优化是我们进阶高级开发工程师的必经之路,而APP启动速度的优化,也是我们开启APP优化的第一步。用户在使用我们的软件时,交互最多最频繁的也就是APP的启动页面,如果启动页面加载过慢,很可能造成用户对我们APP的印象过差,进而消耗了用户的耐心,更严重可能导致用户的卸载行为。这也是微信始终坚持使用“一个小人望着地球”作为启动页面的背景,并且坚持不添加启动广告的的原因。

    二、APP的三种启动方式

    来看一下Google官方文档《Launch-Time Performance》对应用启动优化的概述;

    应用的启动可以分为冷启动,热启动和温启动,而启动最慢、耗时最长的就是冷启动。

    冷启动(cold start)

    当应用启动时,后台没有该应用的进程(常见如:进程被杀、首次启动等),这时系统会重新创建一个新的进程分配给该应用。

    热启动(hot start)

    这种启动会从已有的进程中来启动应用,通俗来讲就是已经启用的应用,通过back键或者home键回到系统主界面,再次通过最近任务重新打开Activity的过程。开销比冷启动更小。

    暖启动(warm start)

    暖启动产生的场景很多。常见如:1。用户使用返回键退出应用,然后马上又重新启动应用。2.应用被内存清除,再次打开应用,会通过OnCreate()中保存的实例状态恢复。

    冷启动是从头开始启动APP,而其他两种启动方式是从后台活动返回到前台的一个过程。热启动和暖启动没有明显的区分界限,我们姑且把热启动和暖启动统称为热启动。开发中我们更多的关注冷启动优化,本文也是从Android的实例从发,分析冷启动的启动过程,并给出冷启动的优化方案。

    三、APP的冷启动过程

    冷启动开始时,系统会依次执行三个任务去启动APP:

    • 加载和启动应用程序
    • APP启动后,立即创建一个空白的启动Window
    • 创建APP的进程

    在这三个任务执行后,系统创建了应用进程,那么应用进程接下来会执行下一步:

    • 创建APP对象
    • 开启一个主线程
    • 创建启动页的Activity
    • 加载View
    • 布局view到屏幕
    • 进行初始绘制显示视图

    当应用进程完成初始绘制之后,系统进程用启动页的Activity来替换当前显示的空白Window,这个时刻用户就可以使用App了。

    四、APP启动时间

    APP的启动时间是我们可以检验优化效果的依据,启动时间是指打开应用从初始化到显示启动页Activity的这一段时间。
    Google官方的解释:APP startup time

    使用过logcat查看启动时间

    在Android4.4(API level 19)以上的Android版本上,当启动应用时Android Studio自动会在logcat中输出启动时间。 这个时间从应用启动(创建进程)开始计算,到完成视图的第一次绘制(即Activity内容对用户可见)为止。

    如Display显示:

    I/ActivityManager: Displayed com.example.app/com.example.app.SplashActivity: +1s742ms (total +49s450ms)
    

    reportFullyDrawn()方法

    Activity 的reportFullyDrawn()方法,
    它会在Logcat里打印从apk初始化到reportFullyDrawn()方法被调用用了多长时间(文章的reportFullyDrawn()SplashActivity中的onCreate()中执行,可以看到显示的时间和Displayed的是一摸一样的)

    I/ActivityManager: Fully drawn com.example.app/com.example.app.SplashActivity: +1s742ms (total +49s450ms)
    

    执行adb命令手动查看启动时间

    adb shell am start -W [packagename]/[packagename.SplashActivity]

    输出:

    Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.example.app/.SplashActivity }
    Status: ok
    Activity: com.example.app/.SplashActivity
    ThisTime: 1368
    TotalTime: 1368
    WaitTime: 1432
    Complete
    
    

    ThisTime:最后一个启动的Activity的启动耗时;

    TotalTime:自己的所有Activity的启动耗时;

    只用关注TotalTime就行了

    启动时间标准

    官方给出,当启动时间超出以下指标时,会被认为启动时间过长,这是就需要考虑仔细优化启动时间。

    • 冷启动时间超过5s
    • 热启动时间超过1.5s
    • 暖启动时间超过2s

    说了一大堆启动的基础知识,下边开始讲解真正的优化实战

    五、启动优化实战

    解决应用刚启动时的白屏问题

    前边讲到,应用初始化会进行一系列进程的创建,资源的初始化工作,这段时间系统会先分配一个空白的Window,这会造成用户打开应用到显示第一个可交互的Activity,会经历一段白屏的时间。

    这时我们可以在给app定义一个主题去解决,在Activity显示出来之前先显示一个主题背景,去填补空白的Window阶段。

    定义一个Splash主题

        <!--Splash launcher-->
        <style name="LauncherTheme" parent="AppTheme">
            <item name="android:windowBackground">@mipmap/ic_splash_bg</item>
            <item name="android:windowFullscreen">true</item>
            <item name="android:windowContentOverlay">@null</item>
        </style>
    

    manifest中引用该主题

     <activity android:name=".activity.SplashActivity"
                android:theme="@style/Launcher">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    

    最后记得在启动页显示以后恢复默认的APP主题

      override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setTheme(R.style.AppTheme)
            setContentView(R.layout.activity_splash)
          
      }
    

    这种方法只是视觉上给用户一种快速启动的感觉,不能减少实际的启动时间。

    避免Application初始化过重

    随着我们工程越做越大,第三方库和组件也逐渐被依赖到我们的项目中,避免不了会在Application的onCreate()中执行很多第三方库的初始化工作。大量的初始化工作导致该生命周期过于沉重,可能会加长应用的启动时间,因此我们应该对这些第三方库进行分类和优化。

    • 必须在onCreate()且是主进程中初始化
    • 可以延迟,但是需要在Application中初始化
    • 可以延迟到启动页的生命周期回调中初始化
    • 延迟到用的时候再初始化

    大家可以根据自身项目去整理代码,可以延迟执行的应该放在IntentService或者Work Thread中进行初始化。

    • 例如EventBus 需要在Activiy中使用的,必须在Application中初始化
    • 例如Bugly ,GrowingIO等类似库的可以放在Work Thread中初始化
    • 例如地图定位、ImageLoad可以延迟到使用之前初始化
    • SplashActivity中网络加载的资源,可以首次加载存放在缓存中,下次启动的时候再显示
    • 注意有些第三方库必须在主线程中初始化
    • 避免耗时操作,如数据库I/O操作不要放在主线程执行
    • 删除无用或重复的代码
    • 减少首屏Activity中的网络请求密度

    相关文章

      网友评论

          本文标题:Android性能优化——启动优化

          本文链接:https://www.haomeiwen.com/subject/zggazqtx.html