編輯:關於Android編程
在上一篇博客中,我和大家一起探討了在Android中對SQLite數據庫的操作優化細節。
今天,我們繼續Android性能優化系列 - 布局優化。在Android中,UI布局作為展示性的標志,顯示的速度直接體現了一個App對於客戶直觀的影響。一個好的App,在布局和UI上肯定有比較好的性能優化,所以布局優化成為了Android性能優化的有一個重點。
Android中關於布局優化,系統為我們提供了幾個抽象的標簽:
(1)include
(2)viewstub
(3)merge
下面,我們就來一一介紹三個標簽的作用和使用方式。
1> include
顧名思義,include標簽可以讓我們復用包含一個layout布局。例如,我們App在大部分情景下都是這樣的設計:topbar -> content -> footbar。
那麼,很多界面都是這樣的布局,我們就可以抽取出topbar和footbar作為公共布局,使用include就可以復用該布局,下面看代碼:
這是一個頭布局:layout_topbar.xml
<!--?xml version="1.0" encoding="utf-8"?--> <linearlayout android:layout_height="wrap_content" android:layout_width="match_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android"> <relativelayout android:id="@+id/rl_root_title_base" android:layout_height="46dp" android:layout_width="match_parent"> <textview android:gravity="center_vertical" android:id="@+id/tv_left_title" android:layout_centervertical="true" android:layout_height="wrap_content" android:layout_marginleft="10dp" android:layout_width="wrap_content" android:textcolor="#80C469"> <textview android:ellipsize="end" android:id="@+id/tv_topic_title" android:layout_centerinparent="true" android:layout_height="wrap_content" android:layout_width="wrap_content" android:maxlength="10" android:singleline="true" android:textcolor="@color/cl_font_46" android:textsize="18dp"> <textview android:gravity="center" android:id="@+id/tv_right_first_title" android:layout_alignparentright="true" android:layout_centervertical="true" android:layout_height="wrap_content" android:layout_marginright="10dp" android:layout_width="wrap_content" android:minheight="30dp" android:minwidth="30dp" android:textcolor="@color/cl_80c469" android:textsize="16dp"> <textview android:gravity="center" android:id="@+id/tv_right_second_title" android:layout_centervertical="true" android:layout_height="wrap_content" android:layout_marginright="10dp" android:layout_toleftof="@id/tv_right_first_title" android:layout_width="wrap_content" android:minheight="30dp" android:minwidth="30dp" android:textcolor="#80C469"> </textview></textview></textview></textview></relativelayout> <view android:background="@color/cl_font_ea" android:id="@+id/line_root_base" android:layout_height="0.5dp" android:layout_width="match_parent"> </view></linearlayout>
main.xml
<linearlayout android:layout_height="match_parent" android:layout_width="match_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <include layout="@layout/layout_top"> </include></linearlayout>
上面代碼中我們使用include的屬性layout來重用topbar布局。include還可以指定layout_width和layout_height以及id。如果指定了id屬性,則被包含的根布局id將會失效,此id將會被覆蓋。
2> viewstub
viewstub標簽和include標簽很相似,都是使用layout屬性來加載一個布局。不同之處是include標簽用來重用布局,該布局會在App啟動加載時被加載進內存。而viewstub標簽所引用的布局是不會被加載出來的,只有當你在某個時間需要使用時才會被加載出來,從而在解析layout時節省了cpu加載時間和內存的占用。
使用也非常簡單,看下面代碼:
<linearlayout android:layout_height="match_parent" android:layout_width="match_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <viewstub android:id="@+id/vstub_network_error" android:layout="@layout/layout_network_error" android:layout_height="match_parent" android:layout_width="match_parent"> </viewstub></linearlayout>
在布局代碼中,我們使用ViewStub的layout來加載一個布局。
private void showEmptyView() { if(ValidateUtils.isNullObj(viewNetWorkError)){ ViewStub mViewStub = (ViewStub) findViewById(R.id.vstub_network_error); viewNetWorkError = mViewStub.inflate(); } else { viewNetWorkError.setVisibility(View.VISIBLE); } }
private void showCourseContent(Course course) {
if(ValidateUtils.isNotNullObj(viewNetWorkError)) { viewNetWorkError.setVisibility(View.GONE); }
}
我們在代碼中通過findViewById來獲取ViewStub,然後調用其inflate方法就可以獲取到layout的view。
ViewStub的使用場景很廣泛:例如顯示加載失敗的界面,進度布局顯示,信息出錯提示等等。
3> merge
merge標簽用來取消layout的層級的顯示。大家都知道,Android頂級布局DecorView的根布局是讓FrameLayout。此時在我們的布局中如果我們使用FrameLayout,就會造成布局節點的層級疊加重復繪制。Android為我們提供了一個叫做hierarchy viewer來查看布局節點信息。該工具在sdk/tools目錄下。
要注意的一點是,merge標簽必須作為布局的根標簽,即不能嵌套在其他布局中。
使用很簡單,就不貼代碼了。
介紹完了以上3個抽象標簽的使用方式,想必大家都知道該如何去應用在自己的布局中來優化布局,下面還有幾點同時也需要大家去關注一下:
(1)inflate:大家都知道,inflate用來在代碼中加載一個現有的布局。例如我們可以使用LayoutInflater.from().inflate()來發加載,同時也可以在Activity中使用getLayoutInflater().inflate()來加載一個布局。但是每次使用inflate去加載布局是有時間和內存消耗的。所以我們要利用復用View來減少不必要的重復inflate。例如上面我們在介紹ViewStub的時候會去inflate。此時我們就可以將該View當做全局變量。下次只需要判斷下是否為null,就可以去重復使用,而不必每次都inflate加載了。
(2)ListView Adapter的getView方法:在該方法中我們都會去inflate一個布局,然後設置一些數據,最後return該View。ListView在每一個Item被渲染加載時都回去重復調用getView。並且ListView的convertView是可以重復利用的,所以我們可以利用ViewHolder的原理來復用convertView,而不必每次都inflate。
(3)使用SurfaceView和TextureView:SurfaceView和TextureView不會占用UI Thread來加載渲染視圖,他們都會開啟一個線程來異步進行加載。所以可以使用他們來優化加載速度及顯示效果。
(4)盡量為所有分辨率創建資源:減少不必要的硬件縮放,這樣會降低UI的繪制速度和占用大量的內存消耗。
注意:之前看到網上很多朋友說將View的可見性設置為gone。該View同樣不會被加載到內存。其實這種說法是錯誤的。從Android源碼可以知道,即使將View的visiablity設置為gone,View同樣會被加載的內存資源當中。即只有只有ViewStub加載的layout在App啟動後才不會被加載到內存資源。
好了,關於布局優化的內容就介紹到這裡了。更多的東西還需要大家去嘗試一下。下一篇我將和大家分享Android性能優化 一 數據優化
本文實例講述了Android編程四大組件之Activity用法。分享給大家供大家參考,具體如下:這裡詳細介紹如何創建Activity、生命周期、內存管理、啟動模式。創建A
仿微信通訊錄右側快速定位字母表控件先看效果圖: 界面比較單調,湊合看,主要看功能。這種控件在很多應用的通訊錄的界面,MIUI裡面的通訊錄都有這個功能,其實這是一
5、Activity用SharedPreferences保存數據,大小有木有限制?個人理解:SharedPreferences是哪種存儲數據的方式竟然記不清楚了,個人印象
MagicalRecordhttps://github.com/magicalpanda/MagicalRecord注意: MagicalRecord 在 ARC 下運作