在启动的过程中,尽量把能在后台做的任务都放到后台,可以使用以下几个方式来执行后台任务:
适当地使用EventBus可以延后一些初始化。在需要的地方post一个事件,EventBus会通知注册过这些事件的地方,这样可以把一些初始化在真实需要的时候再post一个触发事件,然后延后初始化。
EventBus使用3步骤
public static class MessageEvent { /* Additional fields if needed */ }
在需要的地方注册: 可以指定线程模式 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);
}
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()
中做耗时操作。
因为ContentProvider
的onCreate()
会在Application onCreate()
之前调用。
减少View的层级可以有效避免过度绘制,减少不必要的绘制过程。
瞬间产生大量的对象会严重占用Young Generation的内存区域,当达到阀值,剩余空间不够的时候,会触发GC。即使每次分配的对象占用了很少的内存,但是他们叠加在一起会增加Heap的压力,从而触发更多其他类型的GC。这个操作有可能会影响到帧率,并使得用户感知到性能问题。
获取Webview UA可以通过创建要给Webview然后获取setting中的UserAgent,不过为了获取UA而创建Webview是一个比较耗时的操作。我们可以在API17及以上的系统中通过WebSettings.getDefaultUserAgent(context)
快速获取。
Activity的切换是比较耗时的,如果没有必要,我们可以将达到主要页面之前的Activity删除,或者修改成Fragment动态加入。
通过之前的分析以及这篇文章介绍的启动优化方法,我们词典的启动速度得到了50%的提升,有效地提升了用户体验。在以后的开发过程中,当涉及到启动流程的代码时需要格外谨慎,避免有耗时的操作加入。当然目前的词典启动速度还可以进一步优化,可以思考的方向一下几点:1. 进一步优化信息流布局,减少不必要的绘制;2. 深入探索第三方SDK带来的启动速度延迟并尝试优化;3. 获取更多实时广告的成功率并尝试去除实时广告逻辑。
【1】胡凯,2016.Android性能优化典范 - 第5季
【2】胡凯,2016.Android性能优化典范 - 第6季
【3】TellH的博客,2016.实现类似微信Viewpager-Fragment的惰性加载,lazy-loading
本文来自网易实践者社区,经作者申国骏授权发布。