[譯]提升Android應用性能的小貼士

本文譯自Android開發(fā)者網(wǎng)站,主要介紹了提升Android應用性能表現(xiàn)的幾個建議骑丸。閱讀本文時還要務必記得“過早優(yōu)化是萬惡之源”,優(yōu)化起碼應該放在實現(xiàn)了應用的MVP版本之后绪抛。
原文地址:https://developer.android.com/training/articles/perf-tips.html


本文主要介紹了提升Android應用性能的一些小方法崭放,組合使用這些方法往往能夠改善我們所開發(fā)的應用的性能表現(xiàn)。但是扣甲,我們應優(yōu)先關注應用所選用的數(shù)據(jù)結構和算法篮赢,切勿本末倒置。想寫出高效代碼琉挖,有兩個基本原則:

  • 不要做本不必做的工作启泣;
  • 不要分配不必要的內存。

以上兩個基本原則很好理解示辈,第一條是讓我們盡可能降低應用的時間復雜度种远,第二條是讓我們盡可能降低應用的空間復雜度。下文的各個建議實際上也是圍繞著這兩個基本原則展開的顽耳。
當我們對Android應用做優(yōu)化時,我們必須面對的一個最蛋疼的問題之一妙同,便是我們的應用將會在各種類型的設備上運行射富,這意味著它們往往有著不同的硬件架構。不同版本的Android虛擬機在各種硬件架構上會以不同的速率運行粥帚。而我們大多數(shù)情況下無法簡單地斷定胰耗,X設備的速度會是Y設備的多少倍。我們在模擬器上的測試結果芒涡,對我們做真機上的性能評估又往往沒什么幫助柴灯。
更令人蛋疼的是卖漫,支持即時編譯(JIT)的設備和不支持即時編譯的設備又有著巨大的差異——支持即時編譯的設備上的最優(yōu)代碼,對于不支持即時編譯的設備來說赠群,不總是最優(yōu)的羊始。
要確保你的應用在各種各樣的設備上都有著良好的性能表現(xiàn),要確保你的代碼在各種情況下都是高效的查描,這需要我們下一番功夫來對代碼進行優(yōu)化突委。以下是一些性能優(yōu)化的建議。

避免創(chuàng)建不必要的對象

創(chuàng)建對象總是會產生代價的冬三。一個支持線程級分配池的分代垃圾回收器可以使得一次內存分配所花的代價更少匀油,但是再少也少不過“根本不進行內存分配”。
當你的應用中創(chuàng)建了足夠多的對象勾笆,便會導致垃圾回收經(jīng)常發(fā)生敌蚜,這可能會帶來用戶界面的“卡頓”。因此窝爪,你應該避免創(chuàng)建不必要的對象弛车,比如:若你有一個返回一個String的方法,并且你確信返回結果總是會被添加到一個StringBuffer(StringBuilder)中酸舍,那么應對該方法做出修改帅韧,讓它不再返回String,而是直接把結果添加到相應的StringBuffer(StringBuilder)中啃勉,這樣一來便可以避免創(chuàng)建一個臨時的String對象忽舟。
還有一個更“激進”的建議是把多維數(shù)組都“展開”成一維數(shù)組:

  • 多個int數(shù)組要比一個int[]對象數(shù)組更加高效,這對于其他原始數(shù)據(jù)類型(primitive data type)同樣適用淮阐;
  • 若你需要一個存儲(Foo, Bar)元組的容器叮阅,要記得使用Foo數(shù)組和Bar數(shù)組要比使用(Foo, Bar)對象數(shù)組高效的多(例外情況是當你設計API時,為了一個良好的API設計泣特,我們應該在性能上做出小小的妥協(xié))浩姥;

對于本條建議,概括起來就是盡可能避免創(chuàng)建短時存活的對象状您。

盡量使用static而不是virtual

若你不需要訪問對象的字段勒叠,那么請定義你的方法為靜態(tài)(static)方法而不是虛(virtual)方法,這會帶來15%到20%的性能提升膏孟。這同樣也是一個好的編程實踐眯分,因為如此一來我們可以清楚的知道,調用該方法不會改變對象的狀態(tài)柒桑。

對于常量使用static final

考慮下面的聲明:

static int intVal = 42;
static String strVal = "Hello, world!";

當聲明了以上語句的類被初次使用時弊决,編譯器會為之創(chuàng)建一個名為“<clinit>“的類初始化器方法。這個方法會將42存儲在intVal中魁淳,并將字符串“Hello, world!”的引用存儲在strVal中飘诗,稍后我們引用到這兩個變量時与倡,便會通過“字段查找(field lookup)”來訪問它們。

然而通過為以上兩句變量聲明加上“final”關鍵字昆稿,那么intVal和strVal就會變?yōu)閮蓚€常量纺座,訪問它們時便無需通過字段查找,這樣會提升性能貌嫡。

注意:這個優(yōu)化建議只對String和原始數(shù)據(jù)類型有效比驻。

使用增強版循環(huán)語法

增強版循環(huán)語法指的就是for-each寫法,它可以用于數(shù)組以及實現(xiàn)了Iterable接口的集合類岛抄。for-each只有對ArrayList使用時别惦,要比常規(guī)的for循環(huán)慢,對于其他情況夫椭,for-each與常規(guī)for速度相差無幾掸掸。由于for-each能夠簡化代碼編寫,我們優(yōu)先考慮使用它蹭秋;只有我們使用ArrayList并且追求“極致性能”時扰付,才應使用常規(guī)for循環(huán)。

對以下場景考慮使用包(package)而不是私有(private)

考慮下面的代碼:

public class Foo {    
  private class Inner {            
    void stuff() {                  
      Foo.this.doStuff(Foo.this.mValue);            
    }      
  }      
  
  private int mValue;      
  public void run() {            
    Inner in = new Inner();           
    mValue = 27;            
    in.stuff();      
  }      
  private void doStuff(int value) {            
    System.out.println("Value is " + value);      
  }
}

以上代碼的問題在于仁讨,我們在Foo類的私有內部類Inner中訪問了Foo類的私有方法和私有字段羽莺,盡管這在Java語法中是合法的。但是對虛擬機來說洞豁,會將Foo$Inner和Foo視為兩個不同的類盐固,所以虛擬機為了實現(xiàn)內部類對外圍類私有方法/字段的訪問,需要創(chuàng)建兩個充當“溝通紐帶”的方法丈挟,如下:

static int Foo.access$100(Foo foo) {      
  return foo.mValue;
}
static void Foo.access$200(Foo foo, int value) {      
  foo.doStuff(value);
}

也就是說刁卜,內部類Inner要通過上面兩個方法來訪問外圍類的私有字段/方法,這顯然比直接字段訪問的開銷要大曙咽。這種情況下蛔趴,我們可以考慮將mValue和doStuff()的可見性改為默認的包范圍。當然例朱,我們不應該對公共API應用這一點孝情。

避免使用浮點型

對于Android設備,使用浮點數(shù)要比整數(shù)大概慢兩倍洒嗤;而雙精度浮點和單精度浮點在時間效率上相差無幾咧叭,只是前者會占用二倍于后者的存儲空間。還應該注意的是烁竭,有些Android設備在硬件層面上不支持除法。我們在開發(fā)中也要注意這一點吉挣。

學習并使用系統(tǒng)API

有時候對于某種業(yè)務邏輯派撕,與自己實現(xiàn)相比婉弹,我們更應該優(yōu)先使用SDK提供給我們的方法,因為系統(tǒng)提供給我們的實現(xiàn)往往更加高效终吼。一個典型的例子是System.arrayCopy()方法要比我們手動用循環(huán)進行數(shù)組復制快9倍左右(在支持即時編譯的Nexus One設備上)镀赌。

可能無需進行的優(yōu)化

我們先來考慮以下兩個方法:

void doWork(Map map);
void doWork(HashMap map);

在一個不支持即時編譯的設備上,第一個方法只比第二個方法慢一點(6%)际跪;而支持即時編譯的設備上商佛,二者效率的差異就更小了。

我們再來考慮一下”重復訪問字段”和”把字段緩存為局部變量”所帶來的性能差異姆打。在不支持即時編譯的設備上良姆,緩存要比重復訪問快20%,而對于支持即時編譯的設備幔戏,兩者幾乎一樣快玛追。
因此對于以上兩種情況,無需我們費心進行“優(yōu)化”闲延。

記得做性能測試

在你著手進行優(yōu)化之前痊剖,確保你已經(jīng)發(fā)現(xiàn)了性能問題,畢竟“過早優(yōu)化是萬惡之源”垒玲。此外陆馁,還要確保你已經(jīng)精確測試過應用現(xiàn)階段的性能表現(xiàn),否則我們難以衡量優(yōu)化工作的成效合愈。我們可以使用SysTrace和TraceView來量化我們應用的性能表現(xiàn)叮贩。


長按或掃描二維碼關注我們,讓您利用每天等地鐵的時間就能學會怎樣寫出優(yōu)質app想暗。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末妇汗,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子说莫,更是在濱河造成了極大的恐慌杨箭,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件储狭,死亡現(xiàn)場離奇詭異互婿,居然都是意外死亡,警方通過查閱死者的電腦和手機辽狈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門慈参,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人刮萌,你說我怎么就攤上這事驮配。” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵壮锻,是天一觀的道長琐旁。 經(jīng)常有香客問我,道長猜绣,這世上最難降的妖魔是什么灰殴? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮掰邢,結果婚禮上牺陶,老公的妹妹穿的比我還像新娘。我一直安慰自己辣之,他們只是感情好掰伸,可當我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著召烂,像睡著了一般碱工。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上奏夫,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天怕篷,我揣著相機與錄音,去河邊找鬼酗昼。 笑死廊谓,一個胖子當著我的面吹牛,可吹牛的內容都是我干的麻削。 我是一名探鬼主播蒸痹,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼呛哟!你這毒婦竟也來了叠荠?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤扫责,失蹤者是張志新(化名)和其女友劉穎榛鼎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鳖孤,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡者娱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了苏揣。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片黄鳍。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖平匈,靈堂內的尸體忽然破棺而出框沟,到底是詐尸還是另有隱情藏古,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布忍燥,位于F島的核電站校翔,受9級特大地震影響,放射性物質發(fā)生泄漏灾前。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一孟辑、第九天 我趴在偏房一處隱蔽的房頂上張望哎甲。 院中可真熱鬧,春花似錦饲嗽、人聲如沸炭玫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吞加。三九已至,卻和暖如春尽狠,著一層夾襖步出監(jiān)牢的瞬間衔憨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工袄膏, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留践图,地道東北人。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓沉馆,卻偏偏與公主長得像码党,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子斥黑,可洞房花燭夜當晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理揖盘,服務發(fā)現(xiàn),斷路器锌奴,智...
    卡卡羅2017閱讀 134,665評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,180評論 25 707
  • 關于android性能缨叫,內存優(yōu)化 看了些資料整理了下椭符,安卓的性能和內存優(yōu)化的一些方法和注意事項。分享出來耻姥。 隨著技...
    ifeng_max閱讀 1,064評論 0 14
  • 有些惡習 如同這枯萎的頭發(fā) 越是舍不得剪斷 枯萎腐敗的分支就越多 使人看不到絲毫的美好 不如拿起剪刀 狠心勇敢的剪...
    Katrina_小月月閱讀 129評論 6 3
  • 美年體檢销钝,九陽豆?jié){機加盟
    東莞colin閱讀 138評論 0 0