第15章 Android性能優(yōu)化(筆記)

第15章 Android性能優(yōu)化

為什么要性能優(yōu)化?

Android設(shè)備作為一種移動(dòng)設(shè)備,CPU和內(nèi)存往往受到一定的限制。

  1. 過(guò)多的使用內(nèi)存會(huì)導(dǎo)致內(nèi)存溢出,即OOM(Out Of Memory)
  2. 過(guò)多的使用CPU會(huì)導(dǎo)致手機(jī)出現(xiàn)卡頓甚至出現(xiàn)無(wú)法響應(yīng)的情況,即ANR(Application Not Responding)

一些有效的優(yōu)化方法

  • 布局優(yōu)化
    使用<include>、<merge>和<ViewStub>標(biāo)簽
  • 繪制優(yōu)化
    在OnDraw()中一不要?jiǎng)?chuàng)建新的對(duì)象,二不要做耗時(shí)任務(wù)
  • 內(nèi)存泄露優(yōu)化
    養(yǎng)成良好的編程意識(shí)比如注意靜態(tài)變量、單例模式和屬性動(dòng)畫造成的內(nèi)存泄漏
  • 相應(yīng)速度優(yōu)化
    避免ANR,比如不要再主線程里做超過(guò)5s的耗時(shí)任務(wù),不要再onReceive里面做超過(guò)10s的任務(wù),還要注意由于在主線程中等待長(zhǎng)時(shí)間的同步鎖而導(dǎo)致的ANR
  • ListView優(yōu)化
    在Adapter中利用ViewHolder,在滑動(dòng)時(shí)不要加載數(shù)據(jù),開(kāi)啟硬件加速
  • Bitmap優(yōu)化
    利用BitmapFactory.Options對(duì)象對(duì)圖片進(jìn)行壓縮
  • 線程優(yōu)化
    采用線程池從而避免大量的創(chuàng)建銷毀線程,還能控制并發(fā)數(shù)避免阻塞現(xiàn)象
  • 其他優(yōu)化
    • 避免創(chuàng)建過(guò)多的對(duì)象
    • 不要過(guò)多使用枚舉
    • 常量使用static final修飾
    • 使用Android特有的數(shù)據(jù)結(jié)構(gòu)比如SparseArray和Pair等
    • 適當(dāng)使用軟引用和弱引用
    • 采用內(nèi)存緩存LreCache和磁盤緩存DiskLruCache
    • 盡量采用靜態(tài)內(nèi)部類

15.1 Android的性能優(yōu)化方法

本節(jié)介紹了一些有效的性能優(yōu)化方法。

15.1.1 布局優(yōu)化

主要思想:布局中的層級(jí)少了,這就意味著Android的繪制工作少了,那么程序的性能自然就提高了。
主要方法:使用<include>、<merge>和<ViewStub>標(biāo)簽

<include>標(biāo)簽

<include>標(biāo)簽可以將指定布局加載到當(dāng)前的布局文件中,通過(guò)layout屬性來(lái)設(shè)置指定的布局文件,<include>標(biāo)簽只支持帶有android:layout_*這種屬性,而且只要設(shè)定了相關(guān)屬性,就必須存在android:layout_width和android:layout_height這兩個(gè)屬性。使用方法如下所示

    <include layout="@layout/titlebar"/>
<merge>標(biāo)簽

<merge>標(biāo)簽主要要和<include>標(biāo)簽搭配使用,當(dāng)<include>標(biāo)簽的最外層布局和所處的當(dāng)前布局一樣時(shí),比如說(shuō)都是垂直方向的LinearLayout,此時(shí)便可以將<include>標(biāo)簽的最外層布局的LinearLayout改成<merge>標(biāo)簽,如下所示

<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Title"/>
    <TextView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Content"/>
</merge>
<ViewStub>標(biāo)簽

<ViewStub>標(biāo)簽主要是一個(gè)輕量級(jí)的按需加載的布局控件,特點(diǎn)是像<include>標(biāo)簽一樣包含一個(gè)布局文件,還有一個(gè)是可以在必要的時(shí)候顯示和消失,所以ViewStub控件有利于顯示一些網(wǎng)絡(luò)加載或者異常時(shí)的界面。使用方法如下。
在布局文件中:

<ViewStub 
    android:id="@+id/stub"
    android:inflatedId="@+id/titlebar_id"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout="@layout/titlebar"
/>

在代碼中:需要注意的點(diǎn)就是上面inflatedId的理解,它的意思就是包含的根布局id,在上面的代碼中就是titlebar.xml這個(gè)布局的id,然后通過(guò)該id可以獲取到titlebar里的控件,比如下面的tvTitle

view = stub.inflate();
View titleBar = findViewById(R.id.titlebar_id);
tvTitle = (TextView) titleBar.findViewById(R.id.title);

btnSwitch.setOnClickListener(new OnClickListener() {
    
    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        if(view.getVisibility() == View.VISIBLE)
            view.setVisibility(View.GONE);
        else
            view.setVisibility(View.VISIBLE);
            
    }
});

btnChange.setOnClickListener(new OnClickListener() {
    
    int i = 0;
    
    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        tvTitle.setText("i = " + i++);
    }
});

15.1.2 繪制優(yōu)化

繪制優(yōu)化是指View的onDraw方法要避免大量的操作,主要體現(xiàn)在內(nèi)存和CPU兩個(gè)方面:

  1. onDraw中不要?jiǎng)?chuàng)建新的局部對(duì)象
    因?yàn)閛nDraw可能會(huì)被頻繁的調(diào)用而導(dǎo)致大量的對(duì)象被創(chuàng)建,這會(huì)導(dǎo)致占用過(guò)多的內(nèi)存從而頻繁地gc;
  2. onDraw中不要進(jìn)行耗時(shí)的操作
    頻繁的耗時(shí)操作會(huì)占用CPU的時(shí)間大量的時(shí)間,導(dǎo)致程序卡頓

15.1.3 內(nèi)存泄漏優(yōu)化

內(nèi)存泄漏:程序在銷毀時(shí),還有一些引用沒(méi)有被釋放,導(dǎo)致這些對(duì)象占用的內(nèi)存無(wú)法被使用
解決方法:
在開(kāi)發(fā)過(guò)程避免寫出有內(nèi)存泄漏的代碼,以下是幾種容易造成內(nèi)存泄漏的原因

  • 靜態(tài)變量導(dǎo)致的內(nèi)存泄漏
  • 單例模式導(dǎo)致的內(nèi)存泄漏
    需要在不需要時(shí)解除
  • 屬性動(dòng)畫導(dǎo)致的內(nèi)存泄漏
    所以使用屬性動(dòng)畫一定要記得在不可見(jiàn)時(shí)取消動(dòng)畫

15.1.4 響應(yīng)速度優(yōu)化和ANR分析

響應(yīng)速度優(yōu)化的核心思想是避免在主線程做耗時(shí)的操作,將耗時(shí)的操作放在線程里執(zhí)行。同時(shí)還要注意另一種不是很明顯的造成ANR的原因:在主線程中長(zhǎng)時(shí)間等待同步鎖

15.1.5 ListView和Bitmap優(yōu)化

ListView優(yōu)化

ListView優(yōu)化主要發(fā)生在Adapter的getView中,14章里有分析,這里總結(jié)一下

  1. 采用ViewHolder進(jìn)行緩存并且避免在getView中執(zhí)行耗時(shí)操作
  2. 在滑動(dòng)時(shí)不要加載數(shù)據(jù)
  3. 嘗試開(kāi)啟硬件加速
Bitmap優(yōu)化

Bitmap優(yōu)化主要是通過(guò)BitmapFactory的Options對(duì)象進(jìn)行的
方法:利用Options先計(jì)算出采樣率inSampleSize并返回給Options,最后通過(guò)改變的Options對(duì)圖片進(jìn)行壓縮

15.1.6 線程優(yōu)化

線程優(yōu)化主要體現(xiàn)在避免大量的創(chuàng)建和銷毀線程,因此線程優(yōu)化的思想就是使用線程池。使用線程池的好處就是,可以重用線程避免創(chuàng)建和銷毀大量線程,還可以控制并發(fā)數(shù)以避免阻塞

15.1.7 一些性能優(yōu)化建議

  • 避免創(chuàng)建過(guò)多的對(duì)象
  • 不要過(guò)多使用枚舉
  • 常量使用static final修飾
  • 使用Android特有的數(shù)據(jù)結(jié)構(gòu)比如SparseArray和Pair等
  • 適當(dāng)使用軟引用和弱引用
  • 采用內(nèi)存緩存LreCache和磁盤緩存DiskLruCache
  • 盡量采用靜態(tài)內(nèi)部類

15.2 內(nèi)存泄漏分析之MAT工具

15.3 提高程序的可維護(hù)性

本節(jié)主要是講Android的程序設(shè)計(jì)思想,主旨是如何提高代碼的可維護(hù)性和可擴(kuò)展性

代碼風(fēng)格

  1. 命名要規(guī)范
    私有成員以m開(kāi)頭,靜態(tài)成員以s開(kāi)頭,常量則全部用大寫字母表示等等
  2. 代碼的排版上需要留出合理的空白來(lái)區(qū)分不同的代碼塊
  3. 僅為非常關(guān)鍵的代碼添加注釋,其他地方不注釋

層次性

代碼的層次性是指代碼要有分層的概念,不要試圖在一個(gè)方法或者一個(gè)類中去全部實(shí)現(xiàn),而要將它分成幾個(gè)自邏輯,然后每個(gè)子邏輯做自己的事情

擴(kuò)展性

程序的擴(kuò)展性要在寫程序的過(guò)程中時(shí)刻考慮到,考慮著如果這個(gè)邏輯后面發(fā)生了改變那么需要做哪些修改,以及怎么樣才能降低修改的工作量

設(shè)計(jì)模式

恰當(dāng)?shù)厥褂迷O(shè)計(jì)模式可以提高代碼的可維護(hù)性和可擴(kuò)展性,但是Android程序有性能瓶頸,因此要控制設(shè)計(jì)的度,設(shè)計(jì)不能太牽強(qiáng)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,882評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,208評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 175,746評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 62,666評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,477評(píng)論 6 407
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 54,960評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,047評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 42,200評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,726評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,617評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,807評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,327評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,049評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 34,425評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 35,674評(píng)論 1 281
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,432評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,769評(píng)論 2 372

推薦閱讀更多精彩內(nèi)容