爲了便於閱讀, 應邀將Android App性能優化系列, 轉移到掘金原創上來.
掘金的新出的"收藏集"功能能夠用來作系列文集了.html
下面實例分析下App啓動優化怎麼作.java
以以前寫的Github App爲例.android
由於這個App集成了Bugly, Push, Feedback等服務, 因此Application的onCreate有不少第三方平臺的初始化工做...git
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);
}
});
}
}複製代碼
當前冷啓動效果:
github
能夠看到啓動時白屏了很長時間.性能優化
接下來咱們結合咱們上文的理論知識, 和介紹的Traceview工具, 來分析下Application的onCreate耗時.app
Debug.startMethodTracing("GithubApp");
...
Debug.stopMethodTracing();複製代碼
運行程序, 會在sdcard上生成一個"GithubApp.trace"的文件.ide
注意: 須要給程序加上寫存儲的權限:工具
複製代碼
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的背景:
複製代碼
弄一個主題:
- @drawable/logo_splash
複製代碼
寫一個什麼都不作的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中設置其爲啓動屏, 並加上主題:
複製代碼
讓咱們來看下最終的效果:
相比以前, 呈現給用戶的再也不是一個白屏了, 帶上了logo, 固然這個背景要顯示什麼, 咱們能夠根據實際狀況來自定義.
這種優化, 對於有些Application內的初始化工做不能移到子線程作的狀況, 是很是友好的. 能夠避免咱們的App長時間的呈現給用戶一個空白的窗口.
照例, 總結下.
此次關於App啓動時間的優化, 寫了兩篇. 寫這麼多, 仍是想傳達下我的作技術的思想, 也算是我的的經驗回顧, 拋磚引玉.
實際場景可能遠比這個複雜,在此更多的提供一種分析思路~歡迎擴展
矯情了, 仍是總結下本文相關的吧:
本文完整源碼, 請移步Github