Android性能優化之Splash頁應該這樣設計

jopen 8年前發布 | 13K 次閱讀 安卓開發 Android開發 移動開發

目前SplashActivity的設計

目前市場上的應用在啟動時基本上都會先啟動一個SplashActivity,作為一個歡迎界面,為什么這樣設計呢?個人總結有三個優點:

1、可以給用戶更好的體驗

比如:可以由后臺動態的改變歡迎的圖片,或者顯歡迎xxx回來,新浪微博的就是這種交互。

2、可以縮減App的啟動時間

由上一篇博文中知道app啟動的耗時主要是在Application初始化中和MainActivity的界面繪制前,由于MainActivity的業務和布局復雜度肯定比只顯示一張圖片的界面高,所以,加入一個顯示一張圖片的Splash頁可以優化應用的啟動。

3、可以在應用啟動時做更多的事

一般來說SplashActivity一般會設計成停留2到4s不等,或者根據數據的加載程度來動態的設置Splash界面的停留時間,既然停留那么久,那么當然可以在這個界面背后做一些事以備MainActivity的快速顯示,比如:數據的預加載、sp的初始化、網絡請求等。

當然你可能有些疑問,那這樣初始化放在Application中也可以啊?也用異步操作數據也是一樣啊?

答案是不一樣!正如上篇所說的,Application初始化時并不會加載界面,而是在它創建完和初始化完成后,開始創建Activity時才開始繪制Theme中的background和繪制布局,所以用一個輕量的Splash頁給它設置一張背景歡迎圖,這樣就立馬能顯示界面了,而在這個界面中還可以做其它的初始化操作,這樣在視覺上即達到了app的快速啟動,又添加了體驗和做數據的初始化。

相反如果過多的放在Application中,則在點擊app圖標啟動時會感覺延遲,必須要把Application中的東西都做完才進入Activity的配置和繪制中。

目前大多數應用的Splash頁設計的不足之處

目前大多應用的Splash頁設計都是利用一個Activity,取名叫SplashActivity,然后在這個SplashActivity中加入一個背景圖,然后再new Handler().postDelayed()幾秒中,再startActivity跳入主界面,這樣設計看起來非常不錯,既可以在SplashActivity初始化、預加載數據,還可以提高應用的啟動速度。

不過這確實提高了應用的啟動速度,畢竟我們比較快的看到了第一幀——SplashActivity,不過在SplashActivity之后,還需要調到MainActivity啊,雖然MainActivity中的一些數據可以在SplashActivity做預取,不過這中間需要有Intent的傳遞過程,而且MainActivity中布局還沒加載進來,所以還是需要再加載和繪制布局界面,然后才能填入數據,所以這樣看來,在跳轉到MainActivity中,還是需要做界面的繪制和數據的加載(包括Intent的數據傳遞)。

以往的SplashActivity的設計圖

這樣看來上面這個設計流程可以這樣表示:

性能優且體驗棒的Splash頁的設計

從上面這個設計圖來看,其中有些操作能不能去除呢?既能達到app啟動速度的提高,也能對數據的預加載還能減去Splash和MainActivity之間不必要的數據傳遞和View的分開繪制。

答案是能的,既然SplashActivity和MainActivity分開進行操作還是不完美,那么可以考慮把它們合為一起,即:一開始還是顯示MainActivity,SplashActivity變為SplashFragment,然后放一個FrameLayout作為根布局去顯示SplashFragment界面,這樣在SplashFragment顯示時候利用顯示的2~4s間的空隙時間做網絡請求去加載數據,這樣待SplashFragment顯示完后再remove,這樣將看到的是有內容的MainActivity,就不必再去等待網絡請求去返回數據了。當然,這種方式是把load Splash View和ContentView合二為一了一起加載,這可能會影響應用的啟動時間,這時我們可以用ViewStub延遲加載MainActivity中某些View從而減去這個影響。

如下設計:

優化前后效果對比

這里為了測試,我把Splash頁的delay時間都設為2.5s。

優化前:

優化后:

優化后其實是把SplashActivity用Fragment顯示,顯示完后再remove,這樣在顯示的時候,MainActivity中還可以直接加載網絡數據,這樣在顯示完SplashFragment后則直接顯示主頁了,而省去了ProgressBar進度條的網絡加載過程。

代碼:

    private Handler mHandler = new Handler();
//...
    final SplashFragment splashFragment = new SplashFragment();
    final FragmentTransaction transaction = getFragmentManager().beginTransaction();
    transaction.replace(R.id.frame, splashFragment);
    transaction.commit();   
//...
    mHandler.postDelayed(new DelayRunnable(this, splashFragment, mProgressBar), 2500);
//...
    static class DelayRunnable implements Runnable {
        private WeakReference<Context> contextRef;
        private WeakReference<SplashFragment> fragmentRef;
        private WeakReference<ProgressBar> progressBarRef;

        public DelayRunnable(Context context, SplashFragment splashFragment, ProgressBar progressBar) {
            contextRef = new WeakReference<Context>(context);
            fragmentRef = new WeakReference<SplashFragment>(splashFragment);
            progressBarRef = new WeakReference<ProgressBar>(progressBar);
        }

        @Override
        public void run() {
            ProgressBar progressBar = progressBarRef.get();
            if (progressBar != null)
                progressBar.setVisibility(View.GONE);
            Activity context = (Activity) contextRef.get();
            if (context != null) {
                SplashFragment splashFragment = fragmentRef.get();
                if (splashFragment == null)
                    return;
                final FragmentTransaction transaction = context.getFragmentManager().beginTransaction();
                transaction.remove(splashFragment);
                transaction.commit();
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
    }

其中FrameLayout作為MainActivity的根布局用作SplashFragment的全屏顯示。為了更優則可以考慮ViewStub,在SplashFragment顯示時再進行加載額外的View。

關于耦合性,其實很低,Splash頁面有專門一個SplashFragment去配置,而MainActivity只是控制它的加載與remove。

來自: http://blog.csdn.net/u010687392/article/details/50525697

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!