天天看點

android應用的優化建議(轉載)對 Android 開發者有益的 40 條優化建議

首先,這是我在http://www.oschina.net/translate/40-developer-tips-for-android-optimization看到的一片文章,感覺挺有道理的,是以copy過來,已做收藏,如有冒犯,還挺見諒。

下面是開始Android程式設計的好方法:

 找一些與你想做事情類似的代碼

 調整它,嘗試讓它做你像做的事情

 經曆問題

 使用StackOverflow解決問題

對每個你像添加的特征重複上述過程。這種方法能夠激勵你,因為你在保持不斷疊代,不經意中你學到了很多。然而,當你釋出應用時你還要做一些更深入的事情。

從一些可正常工作的代碼到一個可怕的應用程式是一個巨大的跳躍,相比iOS平台Android更是如此 。當在iOS上釋出應用時隻是在一個裝置上跳躍–你的手機–對很多裝置而言都很相似–同樣大小的螢幕,都有很好的硬體,95%上運作相同版本的作業系統。 在Android應用中你不會遇到這種情況。

你的程式必須能夠處理一切:從螢幕,處理器,定制的作業系統,API層級以及任何其他的特定裝置。

這是我對使Android應用舒服起來的個人建議。

在Android世界裡目前有超過100種的不同螢幕尺寸,但解決方法也很豐富。為使你的應用适應不同的螢幕配置有兩件事情你需要确定:

你對不同的螢幕尺寸有一個好的布局和結構

你的圖像在不同分辨率下工作良好

這些都是獨立的任務,你可能有一個超級的tablet布局,但上面的圖形看起來很糟糕。我們會依次讨論他們。

當我們有一系列不同尺寸的大屏手機時,它們之間最大的不同就是螢幕的高度。是以ScrollView和ListView通常可是有效的工作,雖然有時它們

并不能完全覆寫全部螢幕。在OpenSignal中的Dashboard标簽下我們可以看到所有部件一氣呵成,不存在滑動、對于許多進階類型标簽中,滑動

展示并不見得是一件壞事。如果你能夠為你所有的設計比對到各種螢幕上面去,那麼最好不過。否則,這兩個控件會讓你用最小的開發代價來保證你的軟體在大多數

螢幕上正常展示。

android應用的優化建議(轉載)對 Android 開發者有益的 40 條優化建議

2: 使用檔案夾. Android 的資源檔案夾結構非常強大, 它允許開發者将不同的圖檔、字元串、布局檔案、外形、顔色這些資源,在api、代碼、螢幕尺寸等部分. 下面是一個例子,展示了在資源檔案夾下你可以怎樣做:

android應用的優化建議(轉載)對 Android 開發者有益的 40 條優化建議

在 values-small 檔案夾中存放了一個 bools.xml 檔案, 檔案中有如下幾行代碼:

<code>1</code>

<code>&lt;</code><code>resources</code><code>&gt;</code>

<code>2</code>

<code>&lt;</code><code>bool</code> <code>name</code><code>=</code><code>"small_screen"</code><code>&gt;true&lt;/</code><code>bool</code><code>&gt;</code>

<code>3</code>

<code>&lt;/</code><code>resources</code><code>&gt;</code>

在代碼中我可這樣引用:

<code>if</code><code>(getResources().getBoolean(R.bool.small_screen)){</code>

<code>getSupportActionBar().hide();</code>

<code>}</code>

在小尺寸裝置中boolean值将置為true

我此時将是以ActionBar來節省空間. 這段代碼正是非凡的ActionBarSherlock 擴充庫中的一部分,稍後再詳細介紹.

在values-sw360dp檔案夾中,存放對應螢幕寬于360dp的資源檔案。與上面相同的位置,有如下代碼

<code>&lt;</code><code>bool</code> <code>name</code><code>=</code><code>"small_screen"</code><code>&gt;false&lt;/</code><code>bool</code><code>&gt;</code>

對于大螢幕而言,ActionBar就置為了顯示狀态.

我不需要将 bools.xml 檔案放入 values-sw400dp檔案夾中, 因為作業系統會自動按相應路徑搜尋. 例如一個裝置寬 600dp (600/160=3.75 英寸, 這就是我們通常所說的7片裝) 作業系統會在values-sw600dp 和其包含的的檔案夾中搜尋 bools.xml 檔案, 若沒有找到則搜尋 values-sw400dp 檔案夾,在搜尋 values-sw360dp 檔案夾以此類推.

建議3:160dp = 1英寸。320 dp = 2英寸。dp = dip

建議4:你可以用這些目錄結構技巧來應付所有資源類型,比如你的XML布局用指定的系統目錄名稱

來解決這個問題,如:layout-sw360dp目錄可以比對目标寬是360dp的機器。如果你也要支援橫豎屏布局切換的話,可以用如下目錄:

layout-sw360dp-land

layout-sw360dp-port

别急,你有一半的使用者是說阿拉伯語的?那就将布局名稱改為下面的樣子吧:

layout-sw360dp-land-ar

layout-sw360dp-port-ar

前兩個可以适用于所有語言,-ar代表阿拉伯語。

建議5:資源規則簡介:

XXX //例子:沒有添加目錄名:預設-适用于Nexus One,Droid 2,S2

XXX-sw360dp // 比較大的手機 – Galaxy Nexus, S3, S4

XXX-sw600dp // 7〃 平闆

XXX-sw720dp // 10” 平闆

在Kindle裝置有些不同,如下:

XXX-large-mdpi // kindle fire 7〃

XXX-large-hdpi // kindle fire 7〃 HD

建議6:如果你不想裁剪所有的布局檔案,你可以用dimens.xml檔案。你要是留心我上面的文章,你就會注意到在我的values目錄裡有很多dimens.xml,這樣是因為我更喜歡在一個layout.xml裡設定值,在每一個布局檔案裡我喜歡這樣做:

<code>01</code>

<code>&lt;</code><code>ImageView</code>

<code>02</code>

<code>android:layout_centerHorizontal</code><code>=</code><code>"true"</code>

<code>03</code>

<code>android:layout_marginTop</code><code>=</code><code>"@dimen/small_margin"</code>

<code>04</code>

<code>android:layout_width</code><code>=</code><code>"@dimen/dashBoardWidth"</code>

<code>05</code>

<code>android:layout_height</code><code>=</code><code>"@dimen/dashBoardHeight"</code>

<code>06</code>

<code>android:id</code><code>=</code><code>"@+id/dashboard"</code><code>/&gt;</code>

<code>07</code>

<code>08</code>

<code>small_margin是在dimen.xml檔案裡定義的:</code>

<code>09</code>

<code>10</code>

<code>11</code>

<code>12</code>

<code>&lt;</code><code>dimen</code> <code>name</code><code>=</code><code>"small_margin"</code><code>&gt;4dp&lt;/</code><code>dimen</code><code>&gt;</code>

<code>13</code>

這個4dp變量在所有dimen檔案裡。我有個Excel檔案,裡面建立了所有不同的基于不同因素所需的尺寸定義。也許你會問:為什麼不讓android

OS來處理所有尺寸的問題?為什麼不呢,為什麼不用一個values目錄和一個布局目錄來代替所有寫死的數值呢?那當然是可以的,如果設定得當,都會得到

所有的尺寸,但是對于有些元素看起來就不是那麼好計算尺寸了。

建議7:讓空白空間大于圖像空間。讓圖像空間大于按鈕的大小。如果将按鈕,多選框,切換控件放大後是很醜陋的。一個100dip(0.63")大小的按鈕是不想在平闆上顯示為原來兩倍寬度200dip(1.25")的.原因是螢幕變大了,這不是說平闆是給巨人用的。我們可以這樣做,在按鈕增加的空間和圖檔擴充的空間裡添加空白。

建議8:用GraphicalLayout工具快速預覽。GraphicalLayout是WYSIWG XML編輯器。我喜歡直接編寫元素-而不是拖,丢棄的可見程式設計方式,但在添加一些元素之後,可以在GraphicalLayout的下拉選擇菜單裡選擇不同螢幕尺寸進行測試。

android應用的優化建議(轉載)對 Android 開發者有益的 40 條優化建議

這裡有很多選項供你選擇。

建議9:不要把所有的圖檔都縮放了。用布局檔案來适應不同螢幕尺寸的方法隻是成功的一半,布局裡的元素(如:圖檔)也要能在高分辨率的螢幕下良好工作。在概念上比較簡單的方式就是建立一套完整的圖檔目錄并将它們與很多drawable目錄比對起來。

drawable-sw600dp-ldpi

drawable-sw600dp-mdpi

drawable-sw600dp-hdpi

drawable-sw600dp-xhdpi

drawable-sw600dp-xxhdpi

...其它的類似。

不要這樣做:

你不要太盡信書了。

一般來說有drawble-ldpi, drawable-hdpi等目錄就足夠了,不需要将所有的情況都加上。

建議10:避免使用位圖(jpg,png)。對于一些圖示來說,用位圖是個不錯的選擇,因為它們使用簡單。但是如果可以避免使用位圖,你可以節省很多空間。但用不同的方法也可以達到很好的結果。

<code>&lt;</code><code>shape</code>

<code>xmlns:android</code><code>=</code><code>"http://schemas.android.com/apk/res/android"</code>

<code>android:shape</code><code>=</code><code>"rectangle"</code> <code>&gt;</code>

<code>&lt;</code><code>corners</code>

<code>android:bottomRightRadius</code><code>=</code><code>"14dp"</code>

<code>android:bottomLeftRadius</code><code>=</code><code>"14dp"</code>

<code>android:topLeftRadius</code><code>=</code><code>"14dp"</code>

<code>android:topRightRadius</code><code>=</code><code>"14dp"</code><code>/&gt;</code>

<code>&lt;</code><code>gradient</code>

<code>android:startColor</code><code>=</code><code>"@color/off_white"</code>

<code>android:endColor</code><code>=</code><code>"@color/pale_yellow"</code>

<code>android:angle</code><code>=</code><code>"270"</code>

<code>android:type</code><code>=</code><code>"linear"</code><code>/&gt;</code>

<code>14</code>

<code>&lt;</code><code>stroke</code>

<code>15</code>

<code>android:width</code><code>=</code><code>"4dp"</code>

<code>16</code>

<code>android:color</code><code>=</code><code>"@color/osm_darkerblue"</code><code>/&gt;</code>

<code>17</code>

<code>&lt;/</code><code>shape</code><code>&gt;</code>

這裡是定義了一個圓角矩形,一個有漸變的邊(深藍)。你可以在布局檔案的任何地方來引用,而且它可以适應于任何螢幕。用它可以做出理想的按鈕。

建議12:用更多的XML繪圖。再來介紹一個用XML繪圖制作出能更加讓你興奮的例子,下面的雷達背景看起來是不是更加的複雜:

android應用的優化建議(轉載)對 Android 開發者有益的 40 條優化建議

不用位圖對你的UI是沒有壞處的(除過圖示)。

建議13:仍然用更多的XML繪圖(如果必須,就用位圖)。那我們怎樣為天氣信号建構一個超酷的圖示-讓燈泡動态的依據光的強度來進行自動填充,以及怎麼點選指針後讓其旋轉呢?這裡我們用位圖和XML結合起來做個例子:

android應用的優化建議(轉載)對 Android 開發者有益的 40 條優化建議

燈泡我們用PNG圖:icon_magnitude_min(一個空的燈泡)和icon_magnitude_max(充滿光的燈泡),然後我們動态的裁剪後者。為了實作這個目标我是這樣做的:

<code>&lt;</code><code>layer-list</code> <code>xmlns:android</code><code>=</code><code>"http://schemas.android.com/apk/res/android"</code><code>&gt;</code>

<code>&lt;</code><code>item</code>

<code>android:drawable</code><code>=</code><code>"@drawable/icon_magnitude_min"</code>

<code>/&gt;</code>

<code>&lt;</code><code>item</code> <code>&gt;</code>

<code>&lt;</code><code>clip</code>

<code>android:clipOrientation</code><code>=</code><code>"vertical"</code>

<code>android:drawable</code><code>=</code><code>"@drawable/icon_magnitude_max"</code>

<code>android:gravity</code><code>=</code><code>"top"</code>

<code>&lt;/</code><code>item</code><code>&gt;</code>

<code>&lt;/</code><code>layer-list</code><code>&gt;</code>

在java程式中我将得到回形針的引用,然後可以用它來控制光的強度。

建議14: 為什麼要用9-patch (當你可以用XML drawables的時候)? Android

具有使用9-patches 來定義drawables的選擇,有些教程闡述了怎樣用它們來做一個按鈕,這樣可以在伸展的時候保持幾個角不變

(并且避免了像素處理)。如果你已經知道怎樣使用9-patches,可能是從web設計中學會的,那麼它們或許值得一用。如果你對9-patches并

不熟悉,我建議你維持原樣。如果你想适應什麼東西——例如拐角的圓弧或者顔色,建立9個小塊要比建立位圖更多被涉及,這就像回到了圖像編輯器的時代。許多

用9-patches獲得的效果也可以通過XML獲得。

建議15: 通過覆寫onDraw()建立自定義views. 有些事情XML并不十分在行,我們在OpenSignal和WeatherSignal中畫過許多圖像,為此有許多的庫,但是我們要為自定義圖像自己編寫代碼。這很有趣。或許你永遠也不需要做這個,但為了使圖像高度動态并自定義,這經常是唯一可行的辦法。

建議17: 對SVG檔案GZip壓縮.

将它們變得更小它們就會處理的更快。

建議18: SVG庫并不是支援一切. 在一些特定的alpha通道中似乎不能正常工作,你甚至不得不在代碼中将它們剔除。

建議19:在一些android系統裡(如TouchWhizz/HTC Sense/MotoBlur等等),預設的buttons和其他UI元件會跟原生系統裡的看起來差别很大。我希望這不是真的,但事實卻是如此。

建議20:自定義你的UI元件。為了确定你的app在所有的裝置裡看起來是一緻的,你将需要自定義所有的東西。這其實沒有你想象中那麼難,隻要你做到了,你将能更加好地把握到你的app的展示外觀。

建議21:Selectors是建立buttons的利器。我們在上面提到了如何在XML裡定義button的背景,但是你将如何建立一個當按下去會改變的button呢?很簡單:像下面那樣在xml檔案裡定義背景。該xml檔案将接收到button目前狀态并且在外觀上做出相應的改變。

<code>&lt;?</code><code>xml</code> <code>version</code><code>=</code><code>"1.0"</code> <code>encoding</code><code>=</code><code>"utf-8"</code><code>?&gt;</code>

<code>&lt;</code><code>selector</code> <code>xmlns:android</code><code>=</code><code>"http://schemas.android.com/apk/res/android"</code><code>&gt;</code>

<code>&lt;</code><code>item</code> <code>android:state_pressed</code><code>=</code><code>"true"</code> <code>android:drawable</code><code>=</code><code>"@drawable/btn_bg_selected"</code> <code>/&gt;</code>

<code>4</code>

<code>&lt;</code><code>item</code> <code>android:state_focused</code><code>=</code><code>"true"</code> <code>android:drawable</code><code>=</code><code>"@drawable/btn_bg"</code> <code>/&gt;</code>

<code>5</code>

<code>&lt;</code><code>item</code> <code>android:drawable</code><code>=</code><code>"@drawable/btn_bg"</code> <code>/&gt;</code><code>&lt;!-- default --&gt;</code>

<code>6</code>

<code>&lt;/</code><code>selector</code><code>&gt;</code>

建議22:在Honeycomb之前的版本裡時不存在ActionBar跟很多

animation 

樣式的,是以可以使用ActionBarSherlock 跟NineOldAndroids來代替。Jake Wharton寫的Android開源

建議23:在運作慢的手機上測試。你将在運作慢的手機上發現很多問題,同時它讓你抓狂,沒人會喜歡運作慢的程式。

建議24:盡量減少XML布局層次。更多的層次意味着系統将為解析你的代碼付出更多的工作,這将會讓圖像渲染的更慢。

建議25:用Android Lint。在工程目錄上右鍵選擇Eclipse&gt;Android Tools&gt;Run Lint。它将會得到程式的一些資訊,并能提高程式的運作速度,或者它能讓你得代碼更加清爽。

建議26:Android Lint可以得到錯誤資訊。它可以給你的代碼提供很詳細的資訊,并在你出錯之前就可以給做出提示。

建議27:用&lt;merge&gt;可以幫助你減少視圖層次結構。這是一種簡單的方式來去除多餘的層次。好的文章都對此有所解釋,而且在

建議28:用HierarchyViewer可以直覺的看到你布局的層次。這個智能的工具可以顯示布局中有多少層次,而且可以提示出那些可以讓程式變慢。

建議29:如果可以盡量用RelativeLayout。AbsoluteLayout已經過期了,就不要用了。你經常會遇到在RelativeLayout和LinearLayout中做出選擇的情況,那就直接用RelativeLayouot吧,因為它可以讓你減少視圖層次。比如,你想實作一個如下視圖:

盒子 A 在螢幕左半邊 |盒子 B在螢幕右半邊

你首先會想到這麼做:

<code>&lt;</code><code>LinearLayout</code>

<code>android:layout_width=”match_parent”</code>

<code>android:layout_height=”wrap_content”</code>

<code>android:orientation=”horizontal”</code>

<code>&gt;</code>

<code>&lt;</code><code>TextView</code>

<code>android:text=”Box A takes up left half of the screen”</code>

<code>android:layout_width=”0dip”</code>

<code>android:layout_weight=”1″</code>

<code>android:text=”Box B takes up left half of the screen”</code>

<code>18</code>

<code>&lt;/</code><code>LinearLayout</code><code>&gt;</code>

<code>19</code>

<code>That works just fine, but you could also use:</code>

<code>20</code>

<code>&lt;</code><code>RelativeLayout</code>

<code>21</code>

<code>22</code>

<code>23</code>

<code>24</code>

<code>25</code>

<code>26</code>

<code>27</code>

<code>28</code>

<code>29</code>

<code>android:layout_toLeftOf=”@+id/dummy_center”</code>

<code>30</code>

<code>31</code>

<code>&lt;</code><code>View</code>

<code>32</code>

<code>android:id=”@+id/dummy_center”</code>

<code>33</code>

<code>34</code>

<code>android:layout_height=”0dip”</code>

<code>35</code>

<code>android:layout_gravity=”center”</code>

<code>36</code>

<code>37</code>

<code>38</code>

<code>39</code>

<code>40</code>

<code>41</code>

<code>android:layout_toRightOf=”@+id/dummy_center”</code>

<code>42</code>

<code>43</code>

<code>&lt;/</code><code>RelativeLayout</code><code>&gt;</code>

第二個表單比第一個難看的多,事實上是相當的糟糕:我們已經介紹過一個完整的新元素了。但是假如我們要給每個盒子裡加入一個圖檔,一般的我們将這樣做:

盒子 A 在螢幕左半邊 圖檔|盒子 B在螢幕右半邊 圖檔

用第一中方法,你得建立一個有兩個層次的LinearLayout,如果用第二種方法,你可以直接在同一個

RelativeLayout中加入圖檔,比如要指定第一個圖檔必須在“dummy_center”的左邊,而且一個TextView

A必須也在其左側。那麼你就得用7個元素3個視圖層次了(LinearLayout

方式),而(RelativeLayout方式)隻用6個元素2個層次,這樣所有的工作添加完成。

建議30:用一些擴充工具如DDMS。這可以幫助你發現一些不必要的網絡調用、檢視電池使用量、垃圾回收資訊,狀态變化(例子:當回調onStop和onDestroy時)等。LittleEye是我目前比較喜歡的工具。

建議31:用AsyncTasks。Anroid工程團隊受夠了人們經常在UI線程裡面實作網絡調用(譯注:耗時操作,容易阻塞UI重新整理),是以他們實作了一些可産生編譯級錯誤資訊的API。但是仍然在很多app中的一些工作會拖垮UI線程,我們要考慮到UI布局要快以及提高UI的響應性。

建議32:一些Aandroid裝置有100mb空間大小的限制。現在情況已有變化了,但是仍然有很多使用者還

會擔心5Mb大小的app會浪費空間。如果你可以選擇将app裝入SD卡的話,這就不是問題了,但如果你的app需要在onBoot裡啟動的話你就不能裝

入SD卡了(例子:如一些窗體小部件).甚至對于一些新的裝置,如果能很快的下載下傳一個小的APK的話,使用者還是很高興的。

建議33:用XML資源(我發誓上次我已經提醒過了),這将比PNG資源節省很多空間,當你僅僅需要一個可以滿足很多螢幕大小的配置時,一個XML檔案會比能實作同樣功能的PNG省空間。

建議35:在Android開發者控制台裡檢查所有被自動檢測出來的bugs.

建議36: ProGuard現在是預設啟動着的. Proguard太好用了 (提高你app的速度和降低檔案大小),但這也讓StackTraces 非常難以處理。你将需要重新追蹤你的StackTraces,是以你将需要繼續保留在每次建構中建立的Proguard的映射檔案。我把它們都放到以代碼版本号命名的檔案夾裡。

建議37: 為了顯示StackTraces裡的行數,你需要修改ProGuard的配置。确認你的proguard.cfg擁有下面這句話:

-keepattributes SourceFile,LineNumberTable

建議38:使用staged rollouts。測試5%的基礎使用者,并且觀察bug報告。

建議39:使用真實裝置測試平台。Device Anywhere and Perfecto

Mobile提供了虛拟測試平台,在那裡,你可以使用真正的移動裝置。我發現他們有一些笨拙,加入連續不斷地進行測試的話,會導緻有一些糟糕的情況。如果

你在聯合辦公的環境裡工作,或者有一些Android開發的好友,那麼去啟動一個“裝置池”吧。

建議40: 多寫代碼少寫部落格。其實不是的, 分享就是關愛, 我隻是想不出第40條寫什麼是了。

本文中的所有譯文僅用于學習和交流目的,轉載請務必注明文章譯者、出處、和本文連結

繼續閱讀