前言
本節(jié)將介紹一些有效的性能優(yōu)化方法三圆,主要內(nèi)容包括布局優(yōu)化狞换,繪制優(yōu)化、內(nèi)存泄漏優(yōu)化舟肉、響應(yīng)速度優(yōu)化修噪、ListView優(yōu)化、Bitmap優(yōu)化路媚、線程優(yōu)化以及一些性能優(yōu)化建議黄琼,在介紹響應(yīng)速度優(yōu)化的同時(shí)還會(huì)介紹ANR日志的分析方法。
布局優(yōu)化
布局優(yōu)化的思想很簡(jiǎn)單整慎,就是盡量減少布局文件的層級(jí)脏款,這個(gè)道理很淺顯的围苫,布局中的層級(jí)少了,這就意味著Android繪制是的工作量減少了撤师,那么程序的性能自然就提高了剂府。
如何進(jìn)行布局優(yōu)化呢?首先刪除布局中無(wú)用的空間和層級(jí)剃盾,其次有選擇地使用性能較低的ViewGroup周循,比如RelativeLayout。如果布局中既可以使用LinearLayout也可以使用RelativeLayout万俗,那么就采用LinearLayout,這是應(yīng)為RelativeLayout 的功能比較復(fù)雜饮怯,他的布局過(guò)程需要花費(fèi)更多的CPU時(shí)間闰歪。FrameLayout和LinearLayout一樣都是一種簡(jiǎn)單高效的ViewGroup,因此可以考慮使用它們蓖墅,但是很多時(shí)候單純通過(guò)一個(gè)LinearLayout或者FrameLayout 無(wú)法實(shí)現(xiàn)產(chǎn)品效果库倘,需要通過(guò)嵌套的方式來(lái)完成。這種情況下還是建議采用RelativeLayout论矾,因?yàn)閂iewGroup的嵌套就相當(dāng)于增加了布局的層級(jí)教翩,同樣會(huì)降低程序的性能。
布局優(yōu)化的另一種手段是采用<include>標(biāo)簽贪壳、<merge>標(biāo)簽饱亿、ViewStub。<include>標(biāo)簽主要用于布局重用闰靴,<merge>標(biāo)簽一般和<include>標(biāo)簽配合使用彪笼,他可以降低減少布局的層級(jí),ViewStub則提供了按需加載的功能蚂且,當(dāng)需要時(shí)才會(huì)將ViewStub中的布局加載到內(nèi)存中配猫,者提高了程序的初始化效率,下面分別介紹他們的使用方法杏死。
<include>標(biāo)簽
<include>標(biāo)簽可以將一個(gè)指定的布局文件加載到當(dāng)前的布局文件中泵肄。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/bg"
android:orientation="vertical" >
<include
layout="@layout/actionbar_layout"/>
</LinearLayout>
上面代碼中,@layout/actionbar_layout 指定了另一個(gè)布局文件淑翼,通過(guò)這種方式就不用把 actionbar_layout 這個(gè)布局文件的內(nèi)容在重復(fù)一遍了腐巢,這就是<include>的好處。<include>標(biāo)簽只支持以android:layout_開(kāi)頭的 屬性窒舟,比如android:layout_width系忙、android:layout_height,其他屬性是不支持的惠豺,比如android:background银还。當(dāng)然风宁,android:id 這個(gè)屬性是個(gè)特例,如果 <include>指定了這個(gè)id屬性蛹疯,同時(shí)被包含的布局文件的根元素也指定了id屬性 戒财,那么以<include>指定的id屬性為準(zhǔn)。需要注意的是捺弦,如果<include>標(biāo)簽指定了android:layout_這種屬性饮寞,那么要求android:layout_width和android:layout_height必須存在,否則其他android:layout_形式的屬性無(wú)法生效列吼,下面是一個(gè)指定了android:layout_*屬性的實(shí)例幽崩。
<include android:id="@+id/new_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="@layout/actionbar_layout"/>
<merge>標(biāo)簽
<merge>標(biāo)簽一般和<include>標(biāo)簽一起使用從而減少布局的層級(jí)。在上面的實(shí)例中寞钥,由于當(dāng)前布局是一個(gè)豎直方向的LinearLayout,這個(gè)時(shí)候如果被包含的布局文件中也采用了豎直方向的LinearLayout慌申,那么顯然被包含的布局文件中的LinearLayout是多余的,通過(guò)<merge>標(biāo)簽就可以去掉多余的那一層LinearLayout理郑。
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@+id/btn1" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@+id/btn2" />
</merge>
ViewStub
ViewStub繼承了View蹄溉,它非常輕量級(jí)且寬/高都是0,因此它本身不參與任何的布局和繪制過(guò)程您炉。ViewStub的意義在于按需加載所需的布局文件柒爵,在實(shí)際開(kāi)發(fā)中,有很多布局文件在正常情況下不會(huì)顯示赚爵,比如網(wǎng)絡(luò)異常時(shí)的界面棉胀,這個(gè)時(shí)候就沒(méi)有必要再整個(gè)界面初始化的時(shí)候?qū)⑵浼虞d進(jìn)來(lái),通過(guò)ViewStub就可以做到在使用的時(shí)候再加載提高程序初始化時(shí)的性能冀膝。
<ViewStub
android:id="@+id/stub_import"
android:inflatedId="@+id/pane_import"
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="@layout/layout_network_error" />
其中stub_import 是ViewStub 的id膏蚓,而 panel_import 是layout_network_error這個(gè)布局的根元素id。在需要加載ViewStub中布局的時(shí)候畸写,有一下兩種方式:
((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
或者
((ViewStub) findViewById(R.id.stub_import)).inflate();
當(dāng)ViewStub 通過(guò)setVisibility或者inflate方法加載后驮瞧,ViewStub就會(huì)被它內(nèi)部的布局替換掉,這個(gè)時(shí)候ViewStub就不在是整個(gè)布局結(jié)構(gòu)的一部分了枯芬。另外目前ViewStub還不支持<merge>標(biāo)簽论笔。