日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

如何编写高效android代码

發(fā)布時(shí)間:2025/1/21 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何编写高效android代码 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

基于Android相關(guān)設(shè)備作為嵌入式設(shè)備范疇,在書(shū)寫(xiě)App應(yīng)用的時(shí)候要格外關(guān)注效率,并且受電池電量的限制。這就導(dǎo)致嵌入式設(shè)備有諸多考慮、有限處理能力,因此就要求我們盡量去寫(xiě)高效的代碼。本文討論了很多能讓開(kāi)發(fā)者使他們的程序運(yùn)行更有效的方法,遵照這些方法,你可以使你的程序發(fā)揮最大的效力。


引言
對(duì)于占用資源的系統(tǒng),有兩條基本原則:

不要做不必要的事

不要分配不必要的內(nèi)存


所有下面的內(nèi)容都遵照這兩個(gè)原則。

1、避免建立對(duì)象

世界上沒(méi)有免費(fèi)的對(duì)象。雖然GC為每個(gè)線(xiàn)程都建立了臨時(shí)對(duì)象池,可以使創(chuàng)建對(duì)象的代價(jià)變得小一些,但是分配內(nèi)存永遠(yuǎn)都比不分配內(nèi)存的代價(jià)大。
如果你在用戶(hù)界面循環(huán)中分配對(duì)象內(nèi)存,就會(huì)引發(fā)周期性的垃圾回收,用戶(hù)就會(huì)覺(jué)得界面像打嗝一樣一頓一頓的。
所以,除非必要,應(yīng)盡量避免盡力對(duì)象的實(shí)例。下面的例子將幫助你理解這條原則:


?當(dāng)你從用戶(hù)輸入的數(shù)據(jù)中截取一段字符串時(shí),盡量使用substring函數(shù)取得原始數(shù)據(jù)的一個(gè)子串,而不是為子串另外建立一份拷貝。這樣你就有一個(gè)新的String對(duì)象,它與原始數(shù)據(jù)共享一個(gè)char數(shù)組。
如果你有一個(gè)函數(shù)返回一個(gè)String對(duì)象,而你確切的知道這個(gè)字符串會(huì)被附加到一個(gè)StringBuffer,那么,請(qǐng)改變這個(gè)函數(shù)的參數(shù)和實(shí)現(xiàn)方式,直接把結(jié)果附加到StringBuffer中,而不要再建立一個(gè)短命的臨時(shí)對(duì)象。
一個(gè)更極端的例子是,把多維數(shù)組分成多個(gè)一維數(shù)組:

int數(shù)組比Integer數(shù)組好,這也概括了一個(gè)基本事實(shí),兩個(gè)平行的int數(shù)組比(int,int)對(duì)象數(shù)組性能要好很多。同理,這試用于所有基本類(lèi)型的組合。
如果你想用一種容器存儲(chǔ)(Foo,Bar)元組,嘗試使用兩個(gè)單獨(dú)的Foo[]數(shù)組和Bar[]數(shù)組,一定比(Foo,Bar)數(shù)組效率更高。(也有例外的情況,就是當(dāng)你建立一個(gè)API,讓別人調(diào)用它的時(shí)候。這時(shí)候你要注重對(duì)API借口的設(shè)計(jì)而犧牲一點(diǎn)兒速度。當(dāng)然在API的內(nèi)部,你仍要盡可能的提高代碼的效率)
總體來(lái)說(shuō),就是避免創(chuàng)建短命的臨時(shí)對(duì)象。減少對(duì)象的創(chuàng)建就能減少垃圾收集,進(jìn)而減少對(duì)用戶(hù)體驗(yàn)的影響。


2、使用本地方法

當(dāng)你在處理字串的時(shí)候,不要吝惜使用String.indexOf(), String.lastIndexOf()等特殊實(shí)現(xiàn)的方法。這些方法都是使用C/C++實(shí)現(xiàn)的,比起Java循環(huán)快10到100倍。
但也并非要完全使用本地方法,調(diào)用本地方法的代價(jià)要高于調(diào)用解釋方法。所以如果可以避免,就不應(yīng)使用本地方法去做一些并不復(fù)雜的運(yùn)算。


3、選擇虛類(lèi)而不是接口

假設(shè)你有一個(gè)HashMap對(duì)象,你可以將它聲明為HashMap或者M(jìn)ap:


Map myMap1 = new HashMap();

HashMap myMap2 = new HashMap();哪個(gè)更好呢?


按照傳統(tǒng)的觀點(diǎn)Map會(huì)更好些,因?yàn)檫@樣你可以改變他的具體實(shí)現(xiàn)類(lèi),只要這個(gè)類(lèi)繼承自Map接口。傳統(tǒng)的觀點(diǎn)對(duì)于傳統(tǒng)的程序是正確的,但是它并不適合嵌入式系統(tǒng)。調(diào)用一個(gè)接口的引用會(huì)比調(diào)用實(shí)體類(lèi)的引用多花費(fèi)一倍的時(shí)間。如果HashMap完全適合你的程序,那么使用Map就沒(méi)有什么價(jià)值。如果有些地方你不能確定,先避免使用Map,剩下的交給IDE提供的重構(gòu)功能好了。(當(dāng)然公共API是一個(gè)例外:一個(gè)好的API常常會(huì)犧牲一些性能)


?


4、用靜態(tài)方法比虛方法好


如果你不需要訪問(wèn)一個(gè)對(duì)象的成員變量,那么請(qǐng)把方法聲明成static。虛方法執(zhí)行的更快,因?yàn)樗梢员恢苯诱{(diào)用而不需要一個(gè)虛函數(shù)表。另外你也可以通過(guò)聲明體現(xiàn)出這個(gè)函數(shù)的調(diào)用不會(huì)改變對(duì)象的狀態(tài)。


?
5、不用getter和setter


在很多本地語(yǔ)言如C++中,都會(huì)使用getter(比如:i = getCount())來(lái)避免直接訪問(wèn)成員變量(i = mCount)。在C++中這是一個(gè)非常好的習(xí)慣,因?yàn)榫幾g器能夠內(nèi)聯(lián)訪問(wèn),如果你需要約束或調(diào)試變量,你可以在任何時(shí)候添加代碼。在Android上,這就不是個(gè)好主意了。虛方法的開(kāi)銷(xiāo)比直接訪問(wèn)成員變量大得多。在通用的接口定義中,可以依照OO的方式定義getters和setters,但是在一般的類(lèi)中,你應(yīng)該直接訪問(wèn)變量。


?

6、將成員變量緩存到本地


訪問(wèn)成員變量比訪問(wèn)本地變量慢得多,下面一段代碼:

  for (int i = 0; i < this.mCount; i++)


    dumpItem(this.mItems[i]);你應(yīng)該寫(xiě)成:

  int count = this.mCount;


  Item[] items = this.mItems;


  for (int i = 0; i < count; i++)


    dumpItems(items[i]);(顯示的使用”this”是為了表明這些是成員變量)


?
另一個(gè)相似的原則是:永遠(yuǎn)不要在for的第二個(gè)條件中調(diào)用任何方法。如下面方法所示,在每次循環(huán)的時(shí)候都會(huì)調(diào)用getCount()方法,這樣做比你在一個(gè)int先把結(jié)果保存起來(lái)開(kāi)銷(xiāo)大很多。

  for (int i = 0; i < this.getCount();i++)

    dumpItems(this.getItem(i));同樣如果你要多次訪問(wèn)一個(gè)變量,也最好先為它建立一個(gè)本地變量,例如:


protected void drawHorizontalScrollBar(Canvas canvas, int width, int height) {

if (isHorizontalScrollBarEnabled()) {

int size = mScrollBar.getSize(false);

if (size <= 0) {

size = mScrollBarSize;
}


mScrollBar.setBounds(0, height – size, width, height);


mScrollBar.setParams(

computeHorizontalScrollRange(),

computeHorizontalScrollOffset(),

computeHorizontalScrollExtent(), false);

mScrollBar.draw(canvas);
}
}


?這里有4次訪問(wèn)成員變量mScrollBar,如果將它緩存到本地,4次成員變量訪問(wèn)就會(huì)變成4次效率更高的棧變量訪問(wèn)。

順便說(shuō)明一下,就是方法的參數(shù)與本地變量的性能是相同的。


?


7、使用常量


讓我們來(lái)看看這兩段在類(lèi)前面的聲明:

static int intVal = 42;

static String strVal = “Hello, world!”;


編譯器會(huì)生成一個(gè)叫做<clinit>的初始化類(lèi)的方法,當(dāng)類(lèi)第一次被使用的時(shí)候這個(gè)方法會(huì)被執(zhí)行。方法會(huì)將42賦給intVal,然后把一個(gè)指向類(lèi)中常量表的引用賦給strVal。當(dāng)以后要用到這些值的時(shí)候,會(huì)在成員變量表中查找到他們。


我們可以做一些改進(jìn),使用“final”關(guān)鍵字:

static final int intVal = 42;
static final String strVal = “Hello, world!”;

現(xiàn)在,類(lèi)不再需要<clinit>方法,因?yàn)樵诔蓡T變量初始化的時(shí)候,會(huì)將常量直接保存到類(lèi)文件中。用到intVal的代碼被直接替換成42,而使用strVal的會(huì)指向一個(gè)字符串常量,而不是使用成員變量。


將一個(gè)方法或類(lèi)聲明為”final”不會(huì)帶來(lái)性能的提升,但是會(huì)幫助編譯器優(yōu)化代碼。舉例說(shuō),如果編譯器知道一個(gè)”getter”方法不會(huì)被重載,那么編譯器會(huì)對(duì)其采用內(nèi)聯(lián)調(diào)用。

你也可以將本地變量聲明為”final”,同樣,這也不會(huì)帶來(lái)性能的提升。使用”final”只能使本地變量看起來(lái)更清晰些(但是也有些時(shí)候這是必須的,比如在使用匿名內(nèi)部類(lèi)的時(shí)候)。


8、謹(jǐn)慎使用foreach

9、避免使用枚舉

結(jié)束語(yǔ):

為嵌入式系統(tǒng)編寫(xiě)正確高效的代碼的最佳的方法就是去理解你的代碼究竟要做什么。如果你的確想要分配一個(gè)迭代器或者無(wú)論如何都要在Lists上面使用增強(qiáng)循環(huán)語(yǔ)法,那么一定是深思熟慮后的選擇,而不是一個(gè)不小心心的副作用。凡事預(yù)則立,不預(yù)則廢。一定要知道你在做什么。按照你自己的風(fēng)格去編寫(xiě)代碼,但一定要仔細(xì)考慮代碼所作的事,并找到提升速度的方法

總結(jié)

以上是生活随笔為你收集整理的如何编写高效android代码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。