Android 提升進入界面的速度

應用除了有內存佔用、內存泄露、內存抖動等看不見的性能問題外,還有很多看得見的性能問題,比如進入界面慢、點擊反應慢、頁面卡頓等等,這些看得見的體驗問題會嚴重影響用戶使用APP心情,但用戶的情緒又無法通過異常採集、數據分析來發現,儘早優化APP的性能體驗問題非常重要,會在一定程度上提升用戶的留存率。

  本文結合最近一段時間對項目中APP各界面進入速度的優化,總結一下進入界面慢的優化方案。先從Activity的生命週期說起,從一個界面FirstActivity跳轉到另外一個界面SecondActivity,應用必須在走完FirstActivity的onPause方法後纔會跑SecondActivity的onCreate方法,FirstActivity的onStop和onDestory方法不會影響到進入SecondActivity的速度。如果我們要優化從FirstActivity跳轉到SecondActivity的速度,需要從FristActivity的onPause和SecondActivity的onCreate、onStart和onResume方法入手。onStart方法通常乾的事情比較少,頁面之間跳轉慢主要是因爲在FirstActivity的onPause和SecondActivity的onCreate、onResume方法耗時導致,這個過程需要執行的操作主要有:

  • 保存FirstActivity界面中的一些狀態;

  • 加載SecondActivity的佈局;

  • 初始化SecondActivity。

  針對上面的分析我們可以從如下四個方面入手:

  • 耗時任務異步處理;

  • 佈局文件優化;

  • 不可見視圖需要時加載;

  • 應用內慎用多進程。

優化實踐

耗時任務異步處理

  除了Android明令禁止在UI線程中執行網絡操作外,還有一些耗時的操作也不能在UI線程中執行,比如IO操作、耗時較長的邏輯操作(比如算法),在Android中可以通過如下幾種方式來實現異步任務:

  • AsyncTask

  • Thread

  • Timer,TimerTask

  • Handler

  如果是在執行異步任務後需要更新界面,優先考慮使用AsyncTask和Handler,它們提供了刷新UI的方案;如果是定時任務可以考慮使用Handler和Timer,TimerTask;如果是使用Thread和Timer,TimerTask,更新UI時可以通過執行當前Activity的runOnUiThread方法實現更新UI操作。

佈局文件優化 ViewStub

  在優化過程中發現有的界面光是加載佈局就需要500ms左右,再加上界面的初始化和上一個界面的狀態保存操作,頁面跳轉時會有嚴重的遲滯感,對於佈局文件的優化網上有很多有價值的文章,最重要的兩條是:

  • 佈局文件不要嵌套太深;

  • 對於不需要進入界面就需要顯示的視圖,強烈建議使用ViewStub。

  佈局文件嵌套太深標示着需要更多次的佈局、測量和繪製,會導致耗時更多,這個可以使用android自帶的“hierarchyviewer”查看,邊優化邊看效果;但有時候即使佈局足夠扁平,加載佈局文件時還是會比較耗時,因爲佈局文件中的視圖太多了,此時對於不需要進入界面就需要顯示的視圖,可以使用ViewStub來延遲加載,比如加載的進度條、特定狀態下出現的倒計時和動畫等,ViewStub的使用方式如下:

/**
 * 在需要使用下載進度條的地方調用該方法加載下載進度條的佈局
 */
private void initDownloadProgress() {
    if(null == mDownloadViewStub){
        mDownloadViewStub = (ViewStub)findViewById(R.id.downProgressViewStubId);
        View view = mDownloadViewStub.inflate();
        mDownloadProgressLayout = (RelativeLayout) view.findViewById(R.id.progressBackLayoutId);
        mDownLoadProgressBar = (ArrowProgressBar) view.findViewById(R.id.arrowProgressBarId);
        mDownloadProgressLayout.setVisibility(View.GONE);
        mDownloadProgressLayout.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return true;
            }
        });
    }
}

不可見視圖需要時加載

  除了佈局文件的優化外,代碼中不需要立即顯示的視圖和動畫都做成延遲加載,比如AnimationDrawable、TypedArray數組、Typeface、addView等,值得一提的是,初始化AnimationDrawable、TypedArray數組和Typeface會很耗時,並且AnimationDrawable特別耗內存,如果不是進入界面就需要使用,強烈建議在需要使用的地方再初始化,分開初始化可以大大減小頁面初始化的耗時。

應用內慎用多進程

  從FirstActivity跳轉到SecondActivity,如果這兩個界面不屬於同一個進程,首次跳轉的時候會創建一個新的進程,創建進程是比較耗時的,比跳轉到同一進程內的新頁面耗時更多,如果不是必須要在應用內使用多進程,強烈建議不要在應用內使用多進程。

總結

  性能優化是一個持續的過程,界面跳轉效率只是一個性能指標,更快地跳轉對於用戶來說有着更好地體驗,優化界面跳轉速度的步驟如下:

  • 打印執行每一段代碼執行需要的時間;

  • 找到耗時較多的代碼段,可能是setContentView,也有可能是在UI線程中的其它耗時操作;

  • 根據耗時的代碼段找解決辦法;

  • 優化後運行看效果。

特別說明:

  • 初始化AnimationDrawable、TypedArray數組和Typeface會很耗時,並且AnimationDrawable特別耗內存,一定要注意他們的初始化時機;

  • 不要迷信網上的一些優化技巧,一定要結合親身實踐,看數據說話;

  • 只要認真分析,很多地方都會有優化空間,將優化的經驗總結出來,並運用到後續的開發中;

  • 優化APP的性能問題在一定程度上能夠提高用戶的留存率,是一件很有價值的事情。


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