自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Android代碼優(yōu)化小技巧總結(jié)

移動(dòng)開(kāi)發(fā)
這篇文章主要是介紹了一些小細(xì)節(jié)的優(yōu)化技巧,當(dāng)這些小技巧綜合使用起來(lái)的時(shí)候,對(duì)于整個(gè)Android App的性能提升還是有作用的,只是不能較大幅度的提升性能而已。選擇合適的算法與數(shù)據(jù)結(jié)構(gòu)才應(yīng)該是你首要考慮的因素,在這篇文章中不會(huì)涉及這方面。你應(yīng)該使用這篇文章中的小技巧作為平時(shí)寫代碼的習(xí)慣,這樣能夠提升代碼的效率。

前言

這篇文章主要是介紹了一些小細(xì)節(jié)的優(yōu)化技巧,當(dāng)這些小技巧綜合使用起來(lái)的時(shí)候,對(duì)于整個(gè)Android App的性能提升還是有作用的,只是不能較大幅度的提升性能而已。選擇合適的算法與數(shù)據(jù)結(jié)構(gòu)才應(yīng)該是你首要考慮的因素,在這篇文章中不會(huì)涉及這方面。你應(yīng)該使用這篇文章中的小技巧作為平時(shí)寫代碼的習(xí)慣,這樣能夠提升代碼的效率。

[[148948]]

代碼性能優(yōu)化建議

通常來(lái)說(shuō),高效的代碼需要滿足下面兩個(gè)規(guī)則:

  • 不要做冗余的動(dòng)作
  • 如果能避免,盡量不要分配內(nèi)存

代碼的執(zhí)行效果會(huì)受到設(shè)備CPU,設(shè)備內(nèi)存,系統(tǒng)版本等諸多因素的影響。為了確保代碼能夠在不同設(shè)備上都運(yùn)行良好,需要***化代碼的效率。

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

雖然GC可以回收不用的對(duì)象,可是為這些對(duì)象分配內(nèi)存,并回收它們同樣是需要耗費(fèi)資源的。 因此請(qǐng)盡量避免創(chuàng)建不必要的對(duì)象,有下面一些例子來(lái)說(shuō)明這個(gè)問(wèn)題:

  • 如果你需要返回一個(gè)String對(duì)象,并且你知道它最終會(huì)需要連接到一個(gè)StringBuffer,請(qǐng)修改你的實(shí)現(xiàn)方式,避免直接進(jìn)行連接操作,應(yīng)該采用創(chuàng)建一個(gè)臨時(shí)對(duì)象來(lái)做這個(gè)操作.
  • 當(dāng)從輸入的數(shù)據(jù)集中抽取出Strings的時(shí)候,嘗試返回原數(shù)據(jù)的substring對(duì)象,而不是創(chuàng)建一個(gè)重復(fù)的對(duì)象。
  • 一個(gè)稍微激進(jìn)點(diǎn)的做法是把所有多維的數(shù)據(jù)分解成1維的數(shù)組:
  • 一組int數(shù)據(jù)要比一組Integer對(duì)象要好很多。可以得知,兩組1維數(shù)組要比一個(gè)2維數(shù)組更加的有效率。同樣的,這個(gè)道理可以推廣至其他原始數(shù)據(jù)類型。
  • 如果你需要實(shí)現(xiàn)一個(gè)數(shù)組用來(lái)存放(Foo,Bar)的對(duì)象,嘗試分解為Foo[]與Bar[]要比(Foo,Bar)好很多。(當(dāng)然,為了某些好的API的設(shè)計(jì),可以適當(dāng)做一些妥協(xié)。但是在自己的代碼內(nèi)部,你應(yīng)該多多使用分解后的容易。
  • 通常來(lái)說(shuō),需要避免創(chuàng)建更多的對(duì)象。更少的對(duì)象意味者更少的GC動(dòng)作,GC會(huì)對(duì)用戶體驗(yàn)有比較直接的影響。

選擇Static而不是Virtual

如果你不需要訪問(wèn)一個(gè)對(duì)象的值域,請(qǐng)保證這個(gè)方法是static類型的,這樣方法調(diào)用將快15%-20%。這是一個(gè)好的習(xí)慣,因?yàn)槟憧梢詮姆椒暶髦械弥{(diào)用無(wú)法改變這個(gè)對(duì)象的狀態(tài)。

常量聲明為Static Final

先看下面這種聲明的方式


  1. static int intVal = 42
  2. static String strVal = "Hello, world!"

編譯器會(huì)在類***被使用到的時(shí)候,使用初始化方法來(lái)初始化上面的值,之后訪問(wèn)的時(shí)候會(huì)需要先到它那里查找,然后才返回?cái)?shù)據(jù)。我們可以使用static final來(lái)提升性能:


  1. static final int intVal = 42
  2. static final String strVal = "Hello, world!"

這時(shí)再也不需要上面的那個(gè)方法來(lái)做多余的查找動(dòng)作了。 所以,請(qǐng)盡可能的為常量聲明為static final類型的。

避免內(nèi)部的Getters/Setters

像C++等native language,通常使用getters(i = getCount())而不是直接訪問(wèn)變量(i = mCount).這是編寫C++的一種優(yōu)秀習(xí)慣,而且通常也被其他面向?qū)ο蟮恼Z(yǔ)言所采用,例如C#與Java,因?yàn)榫幾g器通常會(huì)做inline訪問(wèn),而且你需要限制或者調(diào)試變量,你可以在任何時(shí)候在getter/setter里面添加代碼。 然而,在Android上,這是一個(gè)糟糕的寫法。Virtual method的調(diào)用比起直接訪問(wèn)變量要耗費(fèi)更多。那么合理的做法是:在面向?qū)ο蟮脑O(shè)計(jì)當(dāng)中應(yīng)該使用getter/setter,但是在類的內(nèi)部你應(yīng)該直接訪問(wèn)變量。 沒(méi)有JIT(Just In Time Compiler)時(shí),直接訪問(wèn)變量的速度是調(diào)用getter的3倍。有JIT時(shí),直接訪問(wèn)變量的速度是通過(guò)getter訪問(wèn)的7倍。 請(qǐng)注意,如果你使用ProGuard, 你可以獲得同樣的效果,因?yàn)镻roGuard可以為你inline accessors.

使用增強(qiáng)的For循環(huán)寫法

請(qǐng)比較下面三種循環(huán)的方法:


  1. static class Foo { 
  2.     int mSplat; 
  3.  
  4. Foo[] mArray = ... 
  5.  
  6. public void zero() { 
  7.     int sum = 0
  8.     for (int i = 0; i < mArray.length; ++i) { 
  9.         sum += mArray[i].mSplat; 
  10.     } 
  11.  
  12. public void one() { 
  13.     int sum = 0
  14.     Foo[] localArray = mArray; 
  15.     int len = localArray.length; 
  16.  
  17.     for (int i = 0; i < len; ++i) { 
  18.         sum += localArray[i].mSplat; 
  19.     } 
  20.  
  21. public void two() { 
  22.     int sum = 0
  23.     for (Foo a : mArray) { 
  24.         sum += a.mSplat; 
  25.     } 

zero()是最慢的,因?yàn)镴IT沒(méi)有辦法對(duì)它進(jìn)行優(yōu)化。

one()稍微快些。

two() 在沒(méi)有做JIT時(shí)是最快的,可是如果經(jīng)過(guò)JIT之后,與方法one()是差不多一樣快的。它使用了增強(qiáng)的循環(huán)方法for-each。
所以請(qǐng)盡量使用for-each的方法,但是對(duì)于ArrayList,請(qǐng)使用方法one()。

使用包級(jí)訪問(wèn)而不是內(nèi)部類的私有訪問(wèn)

參考下面一段代碼


  1. public class Foo { 
  2.     private class Inner { 
  3.         void stuff() { 
  4.             Foo.this.doStuff(Foo.this.mValue); 
  5.         } 
  6.     } 
  7.  
  8.     private int mValue; 
  9.  
  10.     public void run() { 
  11.         Inner in = new Inner(); 
  12.         mValue = 27
  13.         in.stuff(); 
  14.     } 
  15.  
  16.     private void doStuff(int value) { 
  17.         System.out.println("Value is " + value); 
  18.     } 

我們定義了一個(gè)私有的內(nèi)部類(Foo$Inner),它直接訪問(wèn)了外部類中的私有方法以及私有成員對(duì)象。這是合法的,這段代碼也會(huì)如同預(yù)期一樣打印出”Value is 27”。

問(wèn)題是,VM因?yàn)镕oo和(Foo.Inner)是不同的類,會(huì)認(rèn)為在 (Foo.Inner)中直接訪問(wèn)Foo類的私有成員是不合法的。即使Java語(yǔ)言允許內(nèi)部類訪問(wèn)外部類的私有成員。為了去除這種差異,編譯器會(huì)產(chǎn)生一些仿造函數(shù):


  1. /*package*/ static int Foo.access$100(Foo foo) { 
  2.     return foo.mValue; 
  3. /*package*/ static void Foo.access$200(Foo foo, int value) { 
  4.     foo.doStuff(value); 

每當(dāng)內(nèi)部類需要訪問(wèn)外部類中的mValue成員或需要調(diào)用doStuff()函數(shù)時(shí),它都會(huì)調(diào)用這些靜態(tài)方法。這意味著,上面的代碼可以歸結(jié)為,通過(guò)accessor函數(shù)來(lái)訪問(wèn)成員變量。早些時(shí)候我們說(shuō)過(guò),通過(guò)accessor會(huì)比直接訪問(wèn)域要慢。所以,這是一個(gè)特定語(yǔ)言用法造成性能降低的例子。

如果你正在性能熱區(qū)(hotspot:高頻率、重復(fù)執(zhí)行的代碼段)使用像這樣的代碼,你可以把內(nèi)部類需要訪問(wèn)的域和方法聲明為包級(jí)訪問(wèn),而不是私有訪問(wèn)權(quán)限。不幸的是,這意味著在相同包中的其他類也可以直接訪問(wèn)這些域,所以在公開(kāi)的API中你不能這樣做。

避免使用float類型

Android系統(tǒng)中float類型的數(shù)據(jù)存取速度是int類型的一半,盡量?jī)?yōu)先采用int類型。

使用庫(kù)函數(shù)

盡量使用System.arraycopy()等一些封裝好的庫(kù)函數(shù),它的效率是手動(dòng)編寫copy實(shí)現(xiàn)的9倍多。

Tip: Also see Josh Bloch’s Effective Java, item 47.

謹(jǐn)慎使用native函數(shù)

當(dāng)你需要把已經(jīng)存在的native code遷移到Android,請(qǐng)謹(jǐn)慎使用JNI。如果你要使用JNI,請(qǐng)學(xué)習(xí)JNI Tips

關(guān)于性能的誤區(qū)

在沒(méi)有做JIT之前,使用一種確切的數(shù)據(jù)類型確實(shí)要比抽象的數(shù)據(jù)類型速度要更有效率。(例如,使用HashMap要比Map效率更高。) 有誤傳效率要高一倍,實(shí)際上只是6%左右。而且,在JIT之后,他們直接并沒(méi)有大多差異。

關(guān)于測(cè)量

上面文檔中出現(xiàn)的數(shù)據(jù)是Android的實(shí)際運(yùn)行效果。我們可以用Traceview 來(lái)測(cè)量,但是測(cè)量的數(shù)據(jù)是沒(méi)有經(jīng)過(guò)JIT優(yōu)化的,所以實(shí)際的效果應(yīng)該是要比測(cè)量的數(shù)據(jù)稍微好些。

責(zé)任編輯:倪明 來(lái)源: 安卓培訓(xùn)
相關(guān)推薦

2015-09-16 14:47:14

Android性能優(yōu)化代碼

2022-11-24 10:34:05

CSS前端

2022-03-10 08:01:06

CSS技巧選擇器

2009-11-26 10:32:57

PHP代碼優(yōu)化

2009-06-18 11:12:42

Hibernate S優(yōu)化

2019-02-25 07:07:38

技巧React 優(yōu)化

2022-07-20 08:21:00

Java代碼優(yōu)化

2024-09-14 11:23:19

2022-07-04 08:51:43

條件語(yǔ)句JavaScript

2023-11-05 19:46:56

JavaIntelliJ代碼

2017-03-02 10:30:57

AndroidAndroid Stu技巧

2010-01-27 17:45:15

Android應(yīng)用技巧

2012-07-23 10:22:15

Python性能優(yōu)化優(yōu)化技巧

2011-05-10 17:06:05

SEO

2021-03-25 15:19:33

深度學(xué)習(xí)Pytorch技巧

2020-01-16 18:30:07

技術(shù)SQL優(yōu)化

2011-06-14 11:14:10

性能優(yōu)化代碼

2017-12-04 12:29:15

前端JavaScript性能優(yōu)化

2025-04-09 00:01:05

2022-11-29 10:42:46

GoFrame技巧腳手架
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)