赞
踩
因为这个App集成了Bugly, Push, Feedback等服务, 所以Application的onCreate有很多第三方平台的初始化工作...
- public class GithubApplication extends MultiDexApplication {
-
- @Override
- public void onCreate() {
- super.onCreate();
-
- // init logger.
- AppLog.init();
-
- // init crash helper
- CrashHelper.init(this);
-
- // init Push
- PushPlatform.init(this);
-
- // init Feedback
- FeedbackPlatform.init(this);
-
- // init Share
- SharePlatform.init(this);
-
- // init Drawer image loader
- DrawerImageLoader.init(new AbstractDrawerImageLoader() {
- @Override
- public void set(ImageView imageView, Uri uri, Drawable placeholder) {
- ImageLoader.loadWithCircle(GithubApplication.this, uri, imageView);
- }
- });
- }
- }

当前冷启动效果:
可以看到启动时白屏了很长时间.
接下来我们结合我们 上文 的理论知识, 和介绍的Traceview工具, 来分析下Application的onCreate耗时.
- Debug.startMethodTracing("GithubApp");
- ...
- Debug.stopMethodTracing();
运行程序, 会在sdcard上生成一个"GithubApp.trace"的文件.
注意: 需要给程序加上写存储的权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
adb pull /sdcard/GithubApp.trace ~/temp
广告: adb的众多用法, 可以参考我的 另一篇文
既然已经知道了哪些地方耗时长, 我们不妨调整下Application的onCreate实现, 一般来说我们可以将这些初始化放在一个单独的线程中处理, 为了方便今后管理, 这里我用了一个InitializeService的IntentService来做初始化工作.
明确一点, IntentService不同于Service, 它是工作在后台线程的.
InitializeService.java代码如下:
- package com.anly.githubapp.compz.service;
-
- import android.app.IntentService;
- import android.content.Context;
- import android.content.Intent;
- import android.graphics.drawable.Drawable;
- import android.net.Uri;
- import android.widget.ImageView;
-
- import com.anly.githubapp.common.wrapper.AppLog;
- import com.anly.githubapp.common.wrapper.CrashHelper;
- import com.anly.githubapp.common.wrapper.FeedbackPlatform;
- import com.anly.githubapp.common.wrapper.ImageLoader;
- import com.anly.githubapp.common.wrapper.PushPlatform;
- import com.anly.githubapp.common.wrapper.SharePlatform;
- import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader;
- import com.mikepenz.materialdrawer.util.DrawerImageLoader;
-
- /**
- * Created by mingjun on 16/8/25.
- */
- public class InitializeService extends IntentService {
-
- private static final String ACTION_INIT_WHEN_APP_CREATE = "com.anly.githubapp.service.action.INIT";
-
- public InitializeService() {
- super("InitializeService");
- }
-
- public static void start(Context context) {
- Intent intent = new Intent(context, InitializeService.class);
- intent.setAction(ACTION_INIT_WHEN_APP_CREATE);
- context.startService(intent);
- }
-
- @Override
- protected void onHandleIntent(Intent intent) {
- if (intent != null) {
- final String action = intent.getAction();
- if (ACTION_INIT_WHEN_APP_CREATE.equals(action)) {
- performInit();
- }
- }
- }
-
- private void performInit() {
- AppLog.d("performInit begin:" + System.currentTimeMillis());
-
- // init Drawer image loader
- DrawerImageLoader.init(new AbstractDrawerImageLoader() {
- @Override
- public void set(ImageView imageView, Uri uri, Drawable placeholder) {
- ImageLoader.loadWithCircle(getApplicationContext(), uri, imageView);
- }
- });
-
- // init crash helper
- CrashHelper.init(this.getApplicationContext());
-
- // init Push
- PushPlatform.init(this.getApplicationContext());
-
- // init Feedback
- FeedbackPlatform.init(this.getApplication());
-
- // init Share
- SharePlatform.init(this.getApplicationContext());
-
- AppLog.d("performInit end:" + System.currentTimeMillis());
- }
- }

GithubApplication的onCreate改成:
- public class GithubApplication extends MultiDexApplication {
-
- @Override
- public void onCreate() {
- super.onCreate();
-
- // init logger.
- AppLog.init();
-
- InitializeService.start(this);
- }
- }
看看现在的效果:
可以看到提升了很多, 然后还有一点瑕疵, 就是起来的时候会有一个白屏, 如果手机较慢的话, 这个白屏就会持续一段时间, 不太友好.
那么还有没有什么办法优化呢?
Android最新的Material Design有这么个 建议 的. 建议我们使用一个placeholder UI来展示给用户直至App加载完毕.
怎么做呢?
如第3节所言, 当App没有完全起来时, 屏幕会一直显示一块空白的窗口(一般来说是黑屏或者白屏, 根据App主题).
前文理论基础 有说到, 这个空白的窗口展示跟主题相关, 那么我们是不是可以从首屏的主题入手呢? 恰好有一个windowBackground的主题属性, 我们来给Splash界面加上一个主题, 带上我们想要展示的背景.
做一个logo_splash的背景:
- <?xml version="1.0" encoding="utf-8"?>
- <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
- <!-- 底层白色 -->
- <item android:drawable="@color/white" />
-
- <!-- 顶层Logo居中 -->
- <item>
- <bitmap
- android:gravity="center"
- android:src="@drawable/ic_github" />
- </item>
- </layer-list>
弄一个主题:
- <style name="SplashTheme" parent="AppTheme">
- <item name="android:windowBackground">@drawable/logo_splash</item>
- </style>
写一个什么都不做的LogoSplashActivity.
- public class LogoSplashActivity extends BaseActivity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // 注意, 这里并没有setContentView, 单纯只是用来跳转到相应的Activity.
- // 目的是减少首屏渲染
-
- if (AppPref.isFirstRunning(this)) {
- IntroduceActivity.launch(this);
- }
- else {
- MainActivity.launch(this);
- }
- finish();
- }
- }

在AndroidManifest.xml中设置其为启动屏, 并加上主题:
- <activity
- android:name=".ui.module.main.LogoSplashActivity"
- android:screenOrientation="portrait"
- android:theme="@style/SplashTheme">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
让我们来看下最终的效果:
相比之前, 呈现给用户的不再是一个白屏了, 带上了logo, 当然这个背景要显示什么, 我们可以根据实际情况来自定义.
这种优化, 对于有些Application内的初始化工作不能移到子线程做的情况, 是非常友好的. 可以避免我们的App长时间的呈现给用户一个空白的窗口.
照例, 总结下.
这次关于App启动时间的优化, 写了两篇. 写这么多, 还是想传达下个人做技术的思想, 也算是个人的经验回顾, 抛砖引玉.
实际场景可能远比这个复杂,在此更多的提供一种分析思路~欢迎扩展
矫情了, 还是总结下本文相关的吧:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。