【安卓】splash頁啓動優化全解析

問題

一般沒有特殊處理,android啓動的時候,會出現白屏或者黑屏的狀態,體驗很差。究其原因,白屏是app在冷啓動的時候,初始化,系統自動用默認的背景色來填充屏幕。這個默認的背景色和你定義的app主題有關。比如如果你的主題繼承自Theme.AppCompat.Light.NoActionBar,那麼啓動的時候就是白色。

本章就來解決app啓動慢的問題。

解決

我所瞭解到的,一般解決這個問題的方法有兩種:

  1. 將這個背景色改爲透明色。雖然看上去沒有白屏的狀況,但用戶點擊app後,原先白屏的那段時間變成了桌面背景,讓人感覺啓動慢是手機系統的鍋,跟app沒啥。有點甩鍋的意思。

    具體做法是在style中添加主題

    <style name="AppTheme.SplashTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowFullscreen">true</item>
        <item name="android:windowIsTranslucent">true</item>
    </style>
    
    

    注意這裏windowIsTranslucent屬性就是設置背景色透明的關鍵代碼。然後在AndroidManifest中將啓動的那個activitytheme設置爲這個主題

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
```
  1. 第一種方法說白了只是給用戶一個假象,“是你手機系統的問題,不是我app的問題”。既然能把背景改成透明的,那爲什麼不能直接改成我的splash頁的背景圖片呢,這樣白屏的那段時間,先用這個背景圖片,當splash頁加載好的時候,無縫銜接,但用戶看到的就是,”不錯這個很快,點了沒有任何停頓,立馬啓動。“。

    具體方法,只要將剛纔的那個AppTheme.SplashTheme的屬性改一改。

```
這裏的`windowBackground`就是設置背景圖片的關鍵代碼,那段冷啓動的時間,屏幕就被設置成這張圖片。接下來使用一樣,在`AndroidManifest`註冊使用即可。強力推薦。

再優化

搞定了白屏問題,我們再來看看一般app使用splash頁啓動的方法,可能最一般的做法就是將啓動頁做成一個Activity,啓動完跳轉到MainActivity。

SplashActivity -> MainActivity

但是這樣是不是有些浪費,SplashActivity運行期間,app應當可以做一些初始化,加載數據的工作,減輕MainActivity的負擔。所以SplashActivity就不需要了,splash可以使用全屏的dialog代替,用完直接銷燬。如此,app啓動更快了。加載完splash, MainActivity 的數據頁加載好了。

這裏提供一個封裝好的實現:SplashDialog


public class SplashScreen {

    private Dialog splashDialog;
    private Activity activity;

    public SplashScreen(Activity activity) {
        this.activity = activity;
    }

    /**
     * 顯示splash圖片
     *
     * @param millis        停留時間 毫秒
     * 
     */
    public void show(final int millis) {
        Runnable runnable = new Runnable() {
            public void run() {
                DisplayMetrics metrics = new DisplayMetrics();

                final ImageView root = new ImageView(activity);
                root.setMinimumHeight(metrics.heightPixels);
                root.setMinimumWidth(metrics.widthPixels);
                root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT, 0.0F));
                root.setScaleType(ImageView.ScaleType.FIT_XY);

				   //glide加載圖片
                GlideApp.with(activity)
                        .load(URL_SPLASH_IMAGE)
                        .placeholder(R.drawable.splash)
                        .error(R.drawable.splash)
                        .diskCacheStrategy(DiskCacheStrategy.NONE)
                        .into(root);

                splashDialog = new Dialog(activity, android.R.style.Theme_NoTitleBar_Fullscreen);

                Window window = splashDialog.getWindow();
                window.setWindowAnimations(R.style.dialog_anim_fade_out);

                splashDialog.setContentView(root);
                splashDialog.setCancelable(false);
                splashDialog.show();

                final Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    public void run() {
                        removeSplash();
                    }
                }, millis);
            }
        };
        activity.runOnUiThread(runnable);
    }

    private void removeSplash() {
        if (splashDialog != null && splashDialog.isShowing()) {
            splashDialog.dismiss();
            splashDialog = null;
        }
    }
}

這裏我使用了glide來加載圖片,你也可以更改爲自己的加載工具。

MainActivity使用,oncreate之後直接調用,new SplashDialog(this).show(3000);
啓動頁變得只需要一行代碼,而且更快,更方便。ps:別忘了給MainActivity 加上之前的主題。

踩坑

上面提到了第二種方法,設置背景圖片。這裏遇到了一個坑,如果有類似問題可以參考。

我的 MainActivity設置了浸入式的狀態欄,但是沒有設置透明底部導航欄。導致設置背景圖片windowBackground的高度是加上了底部導航欄,也就是說導航欄擋住了一部分的背景圖片,但是SplashDialog加載的圖片是忽略底部導航欄的,這樣這兩張圖就會有個錯位,啓動的時候,會出現圖片的位置移動了一下。

解決方法是,在前面的AppTheme.SplashTheme中,繼承自@android:style/Theme.Light.NoTitleBar.Fullscreen,即老版本的theme,不要繼承自Theme.AppCompat.Light.NoActionBar。原因猜想是,老版本不支持佔用導航欄的空間,自然也就不會有被導航欄擋住的情況。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章