如何优化Androd App启动速度(下篇)

阿凡达2018-07-09 10:59

使用后台线程

  在启动的过程中,尽量把能在后台做的任务都放到后台,可以使用以下几个方式来执行后台任务:

  • AsyncTask: 为UI线程与工作线程之间进行快速的切换提供一种简单便捷的机制。适用于当下立即需要启动,但是异步执行的生命周期短暂的使用场景。
  • HandlerThread: 为某些回调方法或者等待某些任务的执行设置一个专属的线程,并提供线程任务的调度机制。
  • ThreadPool: 把任务分解成不同的单元,分发到各个不同的线程上,进行同时并发处理。
  • IntentService: 适合于执行由UI触发的后台Service任务,并可以把后台任务执行的情况通过一定的机制反馈给UI。

使用EventBus

  适当地使用EventBus可以延后一些初始化。在需要的地方post一个事件,EventBus会通知注册过这些事件的地方,这样可以把一些初始化在真实需要的时候再post一个触发事件,然后延后初始化。

EventBus使用3步骤

  1. 定义事件:
     public static class MessageEvent { /* Additional fields if needed */ }
    
  2. 在需要的地方注册: 可以指定线程模式 thread mode:

     @Subscribe(threadMode = ThreadMode.MAIN)  
     public void onMessageEvent(MessageEvent event) {/* Do something */};
    

    注册与反注册

     @Override
     public void onStart() {
         super.onStart();
         EventBus.getDefault().register(this);
     }
    
     @Override
     public void onStop() {
         super.onStop();
         EventBus.getDefault().unregister(this);
     }
    
  3. 发送事件:
     EventBus.getDefault().post(new MessageEvent());
    
    更详细的使用参见 How to get started with EventBus in 3 steps.

启动闪屏主题设置

  默认的启动闪屏是白色的,某些开发者会通过设置一个透明的启动闪屏主题来隐藏启动加载慢的问题,不过这种做法会影响用户体验。我们可以通过设置一个带logo的启动闪屏主题来让用户感受到在点击桌面图标后马上得到响应。不过这里需要注意启动闪屏主题不能使用很大的图片资源,因为加载这些资源本身也是耗时的。   设置启动闪屏可以在第一个展示的Acitivty设置主题:

AndroidManifest.xml:

<activity
    android:name=".activity.DictSplashActivity"
    android:theme="@style/MyLightTheme.NoActionBar.FullScreen">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

styles.xml:

<style name="MyLightTheme.NoActionBar.FullScreen" parent="MyLightTheme.NoActionBar">
    <item name="android:windowBackground">@drawable/bg_launcher</item>
    <item name="android:windowFullscreen">true</item>
</style>

bg_launcher.xml:

<?xml version="1.0" encoding="utf-8"?><!--
  ~ @(#)bg_launcher.xml, 2017-02-06.
  ~
  ~ Copyright 2014 Yodao, Inc. All rights reserved.
  ~ YODAO PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  -->

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:opacity="opaque">
    <!-- The background color, preferably the same as your normal theme -->
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/background_grey"/>
            <size android:height="640dp" android:width="360dp"/>
        </shape>
    </item>
    <!-- Your product logo - 144dp color version of your app icon -->
    <item>
        <bitmap
            android:gravity="bottom|center"
            android:src="@drawable/splash_bottom" />
    </item>
</layer-list>

效果如下:

其他可以优化的细节

  • 减少广告等业务逻辑时间

  这里属于业务逻辑的优化,可根据不同的应用发掘可以缩短的等待时间。

  • SharePreferences中的commit改为apply

  SharePreferences的操作涉及文件的读写,最好尽量使用apply方法代替commit方法。apply方法会先将结果保存在内存的SharePreferences中并异步地更新SharePreferences文件

  • onPause不要执行太多任务

  在展示另一个Acitivty之前,需要经过上一个Acitvity的onPause()方法,因此在Activity的onPause()方法中不适合有耗时的工作。

  • ContentProvider不要做太多静态初始化以及在onCreate()中做耗时操作。

  因为ContentProvideronCreate()会在Application onCreate()之前调用。

  • 减少View层级

  减少View的层级可以有效避免过度绘制,减少不必要的绘制过程。

  • 注意内存抖动

  瞬间产生大量的对象会严重占用Young Generation的内存区域,当达到阀值,剩余空间不够的时候,会触发GC。即使每次分配的对象占用了很少的内存,但是他们叠加在一起会增加Heap的压力,从而触发更多其他类型的GC。这个操作有可能会影响到帧率,并使得用户感知到性能问题。

  • 用更快的方式获取信息,例如获取Webview UA

  获取Webview UA可以通过创建要给Webview然后获取setting中的UserAgent,不过为了获取UA而创建Webview是一个比较耗时的操作。我们可以在API17及以上的系统中通过WebSettings.getDefaultUserAgent(context)快速获取。

  • 尽量删除没必要的中间过渡Activity,减少Activity切换时间

  Activity的切换是比较耗时的,如果没有必要,我们可以将达到主要页面之前的Activity删除,或者修改成Fragment动态加入。

后记

  通过之前的分析以及这篇文章介绍的启动优化方法,我们词典的启动速度得到了50%的提升,有效地提升了用户体验。在以后的开发过程中,当涉及到启动流程的代码时需要格外谨慎,避免有耗时的操作加入。当然目前的词典启动速度还可以进一步优化,可以思考的方向一下几点:1. 进一步优化信息流布局,减少不必要的绘制;2. 深入探索第三方SDK带来的启动速度延迟并尝试优化;3. 获取更多实时广告的成功率并尝试去除实时广告逻辑。

参考

【1】胡凯,2016.Android性能优化典范 - 第5季

【2】胡凯,2016.Android性能优化典范 - 第6季

【3】TellH的博客,2016.实现类似微信Viewpager-Fragment的惰性加载,lazy-loading

相关阅读:如何优化Androd App启动速度(上篇)

本文来自网易实践者社区,经作者申国骏授权发布。