android提高UI的流暢度

android提高UI的流暢度

Android中所有的界面繪制工作都是在UI線(xiàn)程中進(jìn)行的婴洼,提高UI流暢度的最核心根本在于釋放UI線(xiàn)程。即:不在主線(xiàn)程中做耗時(shí)的操作。

很多人都知道彰亥,耗時(shí)的操作要放到子線(xiàn)程中去做惶室,比如訪(fǎng)問(wèn)網(wǎng)絡(luò)减江,比如讀寫(xiě)sd卡凌那。像這類(lèi)操作大家都會(huì)很自然的想到使用子線(xiàn)程來(lái)完成耗時(shí)的操作阻问,等操作結(jié)束之后拭抬,再通過(guò)Handler通知主線(xiàn)程進(jìn)行界面的更新部默。這是非常正確的方法。但是有一類(lèi)方法造虎,它必須得運(yùn)行在在UI線(xiàn)程中傅蹂,就是布局文件的加載。如果這類(lèi)方法花的時(shí)間太多了累奈,也是會(huì)對(duì)流暢度產(chǎn)生很大的影響贬派。今天我們就來(lái)講講布局文件的優(yōu)化。

加載布局文件澎媒,是必須在UI線(xiàn)程中完成的搞乏。我們通常是在onCreate方法中直調(diào)用setContentView,傳入一個(gè)布局文件的id值戒努,或者是通過(guò)LayoutInflater來(lái)將某一個(gè)布局文件轉(zhuǎn)化成View對(duì)象请敦。其實(shí)這兩種方式的本質(zhì)都是一樣的镐躲,都是將xml文件轉(zhuǎn)換成View對(duì)象。

我們現(xiàn)在要做的事侍筛,就是如何讓xml文件轉(zhuǎn)換成View對(duì)象所花的時(shí)間最少萤皂。做到了這點(diǎn),就可以很大程度的提高UI的流暢度匣椰。

1裆熙、優(yōu)化布局, 減少布局的嵌套層級(jí)

** a、使用drawableXXX屬性**

image.png

如果要實(shí)現(xiàn)這樣一個(gè)效果禽笑,布局文件可以這樣寫(xiě)

<LinearLayout orientation="vertical">

 <ImageView/>

  <TextView/>

</LinearLayout>

優(yōu)化后:

<TextView drawableBottom="@drawable/contact"/>

直接一個(gè)TextView就搞定入录,不需要在外面多一層LinearLayout

** b、多使用RelativeLayout佳镜,少使用LinearLayout**

image.png

如果這樣的布局使用LinearLayout來(lái)做的話(huà)僚稿,那么會(huì)是以下這個(gè)效果

image.png

<LinearLayout orientation="horizontal">

<ImageView/>

<LinearLayout orientation="vertical">

    <LinearLayout orientation="horizontal">

        <TextView/>

        <TextView/>

    </LinearLayout>

    <TextView/>

    <LinearLayout orientation="horizontal">

        <TextView/>

        <TextView/>

    </LinearLayout>

</LinearLayout>

</LinearLayout>

這樣就莫名其妙的多出了好多個(gè)LinearLayout.

這樣過(guò)多的LinearLayout嵌套LinearLayout,會(huì)造成UI加載的非常慢蟀伸。這樣的布局完全可以使用一個(gè)RelativeLayout來(lái)完成蚀同,里面的子元素根據(jù)相對(duì)于其他控件的位置即可確定。

嵌套使用LinearLayout很容易會(huì)導(dǎo)致視圖層級(jí)過(guò)深啊掏。如果使用layout_weight這個(gè)參數(shù)不斷的進(jìn)行嵌套蠢络,有可能會(huì)讓各個(gè)子View付出計(jì)算兩次的昂貴代價(jià)

優(yōu)化后代碼:

<RelativeLayout>

<Image id=avatar layout_alignParentLeft=true />

<TextView id=name layout_alignParentTop=true layout_toRightOf=@id/avatar />

<TextView id=location layout_alignParentTop=true layout_toRightOf=@id/name />

<TextView id=desc layout_below=@id/location layout_toRightOf=@id/avatar />

....

</RelativeLayout>

** c、使用merge標(biāo)簽**

使用merge標(biāo)簽也是能夠減少一些布局的層次脖律。merge標(biāo)簽經(jīng)常會(huì)和include標(biāo)簽相聯(lián)系谢肾。

那么什么時(shí)候使用merge標(biāo)簽?zāi)兀肯旅媾e例子說(shuō)明小泉。

<LinearLayout orientation="vertical">

......

<include layout="@layout/include_view_layout"/>

......

</LinearLayout>

而include_view_layout.xml 的代碼如下:

<LinearLayout orientation="vertical">

<Button/>

<Button/>

</LinearLayout>

我們看到Button的父控件是LinearLayout芦疏,而include的父控件也是LinearLayout,這樣子的布局最終的結(jié)果是

<LinearLayout orientation="vertical">

<LinearLayout orientation="vertical">

    <Button/>

    <Button/>

</LinearLayout>

</LinearLayout>

紅色部分的LinearLayout完全是多余微姊,于是這時(shí)候酸茴,我們就可以在include_view_layout.xml文件中使用merge標(biāo)簽了。如下:

<merge>

<Button/>

<Button/>

</merge>

這樣兢交,在加載這個(gè)include標(biāo)簽的時(shí)候薪捍,系統(tǒng)會(huì)忽略merge標(biāo)簽,直接將merge標(biāo)簽內(nèi)的元素添加到外層的LinearLayout去了配喳,達(dá)到減少層級(jí)的效果酪穿。

2、延遲加載

在開(kāi)發(fā)某些功能時(shí)候晴裹,有時(shí)候需要?jiǎng)討B(tài)的根據(jù)條件來(lái)判斷顯示哪一個(gè)View被济,不顯示哪一個(gè)View。一般的做法是將所有的View都寫(xiě)在布局文件中去涧团,然后根據(jù)條件再來(lái)設(shè)置他們的可見(jiàn)度Visibility為GONE或者VISIBLE只磷。這種做法邏輯簡(jiǎn)單经磅,便于理解。但是缺點(diǎn)就是那些不顯示出來(lái)的View也占用了內(nèi)存钮追,消耗了inflate的時(shí)間预厌。因?yàn)橐粋€(gè)View,不論他的Visibility的值是什么元媚,它都會(huì)被inflate出來(lái)轧叽,并占用內(nèi)存空間。這時(shí)候其實(shí)就可以用到延遲加載的控件ViewStub了惠毁。

 ViewStub是一個(gè)非常輕量級(jí)的控件犹芹,它占的資源非常小。注意鞠绰,是ViewStub這個(gè)對(duì)象所占的資源小,但是你可以為ViewStub指定一個(gè)布局文件飒焦,這個(gè)布局文件被inflate的時(shí)候占的空間有可能很大蜈膨。默認(rèn)的情況下,ViewStub的所指定的布局文件是不被inflate的牺荠,只有當(dāng)你調(diào)用了ViewStub的inflate方法時(shí)翁巍,ViewStub所指向的布局文件才會(huì)被inflate。所以ViewStub是一個(gè)延遲加載的控件休雌。

<LinearLayout

android:orientation="vertical"  

android:layout_width="fill_parent"  

android:layout_height="fill_parent"  

android:gravity="center_horizontal">  

<ViewStub

 android:id="@+id/viewstub1"  

 android:layout_width="wrap_content"  

 android:layout_height="wrap_content"    

 android:layout="@layout/viewstub_layout1"/>  

<ViewStub

 android:id="@+id/viewstub2"  

 android:layout_width="wrap_content"  

 android:layout_height="wrap_content"   

 android:layout="@layout/viewstub_layout2"/>  

</LinearLayout>

在java代碼中使用

ViewStub stub1 = (ViewStub) findViewById(R.id.viewstub1);

ViewStub stub2 = (ViewStub) findViewById(R.id.viewstub2);

if(isLogin()) {

stub1.inflate();

} else {

stub2.inflate();

}

這樣就不會(huì)有浪費(fèi)資源空間去加載沒(méi)必要的控件了灶壶。

3、減少inflate的次數(shù)

這個(gè)的典型例子就是ListView的優(yōu)化杈曲。我們說(shuō)ListView的優(yōu)化驰凛,實(shí)際上說(shuō)的就是Adapter中g(shù)etView方法的優(yōu)化,我們來(lái)看一個(gè)沒(méi)有優(yōu)化過(guò)的getView方法担扑。

@Override

public View getView(int position, View convertView, ViewGroup parent) {

MyItem product = list.get(position);

convertView = getLayoutInflater()

.inflate(R.layout.item_record, null);

TextView tvDate = (TextView) convertView

            .findViewById(R.id.tvDate);

TextView tvYongtu = (TextView) convertView

            .findViewById(R.id.tvYongtu);

TextView tvMoney = (TextView) convertView

            .findViewById(R.id.tvMoney);

 tvDate.setText(product.detaildate);

 tvYongtu.setText(product.auditmessage);

 tvMoney.setText(product.detailmoney);

 return convertView;

}

我們知道恰响,ListView中的每一個(gè)Item被顯示出來(lái)都要調(diào)用getView方法,這個(gè)Item如果滑出屏幕涌献,又滑回來(lái)胚宦,重新顯示在界面上的時(shí)候,又會(huì)再次調(diào)用getView方法燕垃。所以getView是不斷的被調(diào)用的枢劝。而上面的代碼,只要調(diào)用了getView方法卜壕,就一定會(huì)去inflate一個(gè)布局文件您旁,真簡(jiǎn)直就是不敢想象的非常耗時(shí)的操作。于是印叁,利用系統(tǒng)給我們的緩存convertView進(jìn)行判斷被冒,可以大大減少inflate的次數(shù)军掂。其實(shí),findViewById也是一個(gè)很耗時(shí)的操作昨悼,我們可以利用ViewHolder來(lái)減少findViewById的次數(shù)蝗锥。優(yōu)化后的代碼如下:

@Override

public View getView(int position, View convertView, ViewGroup parent) {

MyItem product = list.get(position);

ViewHolder holder;

if (convertView == null) {

    convertView = getLayoutInflater().inflate(

            R.layout.item_record, null);

    holder = new ViewHolder();

    holder.tvDate = (TextView) convertView

            .findViewById(R.id.tvDate);

    holder.tvYongtu = (TextView) convertView

            .findViewById(R.id.tvYongtu);

    holder.tvMoney = (TextView) convertView

            .findViewById(R.id.tvMoney);

    convertView.setTag(holder);

} else {

    holder = (ViewHolder) convertView.getTag();

}

holder.tvDate.setText(product.detaildate);

holder.tvYongtu.setText(product.auditmessage);

holder.tvMoney.setText(product.detailmoney);

return convertView;

}

static class ViewHolder {

TextView tvDate;

TextView tvYongtu;

TextView tvMoney;

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市率触,隨后出現(xiàn)的幾起案子终议,更是在濱河造成了極大的恐慌,老刑警劉巖葱蝗,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件穴张,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡两曼,警方通過(guò)查閱死者的電腦和手機(jī)皂甘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)悼凑,“玉大人偿枕,你說(shuō)我怎么就攤上這事』П瑁” “怎么了渐夸?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)渔欢。 經(jīng)常有香客問(wèn)我墓塌,道長(zhǎng),這世上最難降的妖魔是什么奥额? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任苫幢,我火速辦了婚禮,結(jié)果婚禮上披坏,老公的妹妹穿的比我還像新娘态坦。我一直安慰自己,他們只是感情好棒拂,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布伞梯。 她就那樣靜靜地躺著,像睡著了一般帚屉。 火紅的嫁衣襯著肌膚如雪谜诫。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天攻旦,我揣著相機(jī)與錄音喻旷,去河邊找鬼。 笑死牢屋,一個(gè)胖子當(dāng)著我的面吹牛且预,可吹牛的內(nèi)容都是我干的槽袄。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼锋谐,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼遍尺!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起涮拗,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤乾戏,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后三热,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體鼓择,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年就漾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了呐能。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡从藤,死狀恐怖催跪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情夷野,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布荣倾,位于F島的核電站悯搔,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏舌仍。R本人自食惡果不足惜妒貌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望铸豁。 院中可真熱鬧灌曙,春花似錦、人聲如沸节芥。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)头镊。三九已至蚣驼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間相艇,已是汗流浹背颖杏。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坛芽,地道東北人留储。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓翼抠,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親获讳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子阴颖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354