對 Android 開發者有益的 40 條優化建議

下面是開始Android編程的好方法:html

  •  找一些與你想作事情相似的代碼
  •  調整它,嘗試讓它作你像作的事情
  •  經歷問題
  •  使用StackOverflow解決問題

  對每一個你像添加的特徵重複上述過程。這種方法可以激勵你,由於你在保持不斷迭代,不經意中你學到了不少。然而,當你發佈應用時你還要作一些更深刻的事情。java

  從一些可正常工做的代碼到一個可怕的應用程序是一個巨大的跳躍,相比iOS平臺Android更是如此 。當在iOS上發佈應用時只是在一個設備上跳躍–你的手機–對不少設備而言都很類似–一樣大小的屏幕,都有很好的硬件,95%上運行相同版本的操做系統。在Android應用中你不會遇到這種狀況。android

  你的程序必須可以處理一切:從屏幕,處理器,定製的操做系統,API層級以及任何其餘的特定設備。web

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

 目標屏幕尺寸及解決方法

  在Android世界裏目前有超過100種的不一樣屏幕尺寸,但解決方法也很豐富。爲使你的應用適應不一樣的屏幕配置有兩件事情你須要肯定:api

  1. 你對不一樣的屏幕尺寸有一個好的佈局和結構
  2. 你的圖像在不一樣分辨率下工做良好

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

 爲不一樣的屏幕而設計

  1.一般會用ScrollView 和 ListView 輕鬆搞定

  當咱們有一系列不一樣尺寸的大屏手機時,它們之間最大的不一樣就是屏幕的高度。所以ScrollView和ListView一般但是有效的工做,雖然有時它們並不能徹底覆蓋所有屏幕。在OpenSignal中的Dashboard標籤下咱們能夠看到全部部件一鼓作氣,不存在滑動、對於許多高級類型標籤中,滑動展現並不見得是一件壞事。若是你可以爲你全部的設計匹配到各類屏幕上面去,那麼最好不過。不然,這兩個控件會讓你用最小的開發代價來保證你的軟件在大多數屏幕上正常展現。app

opensignal_dashboard1

  Dashboard style 的設計不須要scroll

  2: 使用文件夾. Android 的資源文件夾結構很是強大, 它容許開發者將不一樣的圖片、字符串、佈局文件、外形、顏色這些資源,在api、代碼、屏幕尺寸等部分. 下面是一個例子,展現了在資源文件夾下你能夠怎樣作:編輯器

Screen Shot 2013-07-29 at 10.32.18

  在 values-small 文件夾中存放了一個 bools.xml 文件, 文件中有以下幾行代碼:ide

1
2
3
< resources >
< bool name = "small_screen" >true</ bool >
</ resources >

  在代碼中我可這樣引用:

1
2
3
if (getResources().getBoolean(R.bool.small_screen)){
getSupportActionBar().hide();
}

  在小尺寸設備中boolean值將置爲true 我此時將所以ActionBar來節省空間. 這段代碼正是非凡的ActionBarSherlock 擴展庫中的一部分,稍後再詳細介紹. 在values-sw360dp文件夾中,存放對應屏幕寬於360dp的資源文件。與上面相同的位置,有以下代碼

1
2
3
< resources >
< bool name = "small_screen" >false</ bool >
</ resources >

  對於大屏幕而言,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

  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裏設置值,在每個佈局文件裏我喜歡這樣作:

1
2
3
4
5
6
7
8
9
10
11
12
13
< ImageView
android:layout_centerHorizontal = "true"
android:layout_marginTop = "@dimen/small_margin"
android:layout_width = "@dimen/dashBoardWidth"
android:layout_height = "@dimen/dashBoardHeight"
android:id = "@+id/dashboard" />
 
small_margin是在dimen.xml文件裏定義的:
 
< resources >
 
< dimen name = "small_margin" >4dp</ dimen >
</ resources >

  這個4dp變量在全部dimen文件裏。我有個Excel文件,裏面建立了全部不一樣的基於不一樣因素所需的尺寸定義。也許你會問:爲何不讓android OS來處理全部尺寸的問題?爲何不呢,爲何不用一個values目錄和一個佈局目錄來代替全部寫死的數值呢?那固然是能夠的,若是設置得當,都會獲得全部的尺寸,可是對於有些元素看起來就不是那麼好計算尺寸了。

  建議7:讓空白空間大於圖像空間。讓圖像空間大於按鈕的大小。若是將按鈕,多選框,切換控件放大後是很醜陋的。一個100dip(0.63")大小的按鈕是不想在平板上顯示爲原來兩倍寬度200dip(1.25")的.緣由是屏幕變大了,這不是說平板是給巨人用的。咱們能夠這樣作,在按鈕增長的空間和圖片擴展的空間裏添加空白。

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


  這裏有不少選項供你選擇。

 圖片縮放

  建議9:不要把全部的圖片都縮放了。用佈局文件來適應不一樣屏幕尺寸的方法只是成功的一半,佈局裏的元素(如:圖片)也要能在高分辨率的屏幕下良好工做。在概念上比較簡單的方式就是建立一套完整的圖片目錄並將它們與不少drawable目錄匹配起來。

  drawable-sw600dp-ldpi
  drawable-sw600dp-mdpi
  drawable-sw600dp-hdpi
  drawable-sw600dp-xhdpi
  drawable-sw600dp-xxhdpi
  ...其它的相似。

  不要這樣作:

  你不要太盡信書了。

  通常來講有drawble-ldpi, drawable-hdpi等目錄就足夠了,不須要將全部的狀況都加上。

  建議10:避免使用位圖(jpg,png)。對於一些圖標來講,用位圖是個不錯的選擇,由於它們使用簡單。可是若是能夠避免使用位圖,你能夠節省不少空間。但用不一樣的方法也能夠達到很好的結果。

  建議11:用XML繪圖。位圖均可以用XML繪圖來代替的。XML繪圖不是萬能的,可是它的方便性仍是使我感到驚訝。Android開發文檔中有詳細的介紹,這裏有個簡單的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
< shape
xmlns:android = "http://schemas.android.com/apk/res/android"
android:shape = "rectangle" >
< corners
android:bottomRightRadius = "14dp"
android:bottomLeftRadius = "14dp"
android:topLeftRadius = "14dp"
android:topRightRadius = "14dp" />
< gradient
android:startColor = "@color/off_white"
android:endColor = "@color/pale_yellow"
android:angle = "270"
android:type = "linear" />
< stroke
android:width = "4dp"
android:color = "@color/osm_darkerblue" />
</ shape >

  這裏是定義了一個圓角矩形,一個有漸變的邊(深藍)。你能夠在佈局文件的任何地方來引用,並且它能夠適應於任何屏幕。用它能夠作出理想的按鈕。

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

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

  建議13:仍然用更多的XML繪圖(若是必須,就用位圖)。那咱們怎樣爲天氣信號構建一個超酷的圖標-讓燈泡動態的依據光的強度來進行自動填充,以及怎麼點擊指針後讓其旋轉呢?這裏咱們用位圖和XML結合起來作個例子:

  燈泡咱們用PNG圖:icon_magnitude_min(一個空的燈泡)和icon_magnitude_max(充滿光的燈泡),而後咱們動態的裁剪後者。爲了實現這個目標我是這樣作的:

1
2
3
4
5
6
7
8
9
10
11
12
< layer-list xmlns:android = "http://schemas.android.com/apk/res/android" >
< item
android:drawable = "@drawable/icon_magnitude_min"
/>
< item >
< clip
android:clipOrientation = "vertical"
android:drawable = "@drawable/icon_magnitude_max"
android:gravity = "top"
/>
</ item >
</ layer-list >

  在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中畫過許多圖像,爲此有許多的庫,可是咱們要爲自定義圖像本身編寫代碼。這頗有趣。或許你永遠也不須要作這個,但爲了使圖像高度動態並自定義,這常常是惟一可行的辦法。

  建議16:在不能使用XML的地方使用SVG. 有時候覆蓋onDraw()並勤勤懇懇的爲自定義view編寫代碼畫出須要的線條與弧線是過於技術化了。畢竟有一種矢量圖像語言,它稱做…Scalable Vector Graphics(可擴展矢量圖形)。它也是史上最酷的Android應用之一—Androidify的動力來源。事實上他們建立這個庫就是爲了那款應用,他們將它發佈在這裏:SVG for Android  。這也就是咱們在OpenSignal中畫儀表盤所用到的。

  建議17: 對SVG文件GZip壓縮. 將它們變得更小它們就會處理的更快。

  建議18: SVG庫並非支持一切. 在一些特定的alpha通道中彷佛不能正常工做,你甚至不得不在代碼中將它們剔除。

 達到在android全部版本里表示展示一致的目標

  建議19:在一些android系統裏(如TouchWhizz/HTC Sense/MotoBlur等等),默認的buttons和其餘UI組件會跟原生系統裏的看起來差異很大。我但願這不是真的,但事實倒是如此。

  建議20:自定義你的UI組件。爲了肯定你的app在全部的設備裏看起來是一致的,你將須要自定義全部的東西。這其實沒有你想象中那麼難,只要你作到了,你將能更加好地把握到你的app的展現外觀。

  建議21:Selectors是建立buttons的利器。咱們在上面提到了如何在XML裏定義button的背景,可是你將如何建立一個當按下去會改變的button呢?很簡單:像下面那樣在xml文件裏定義背景。該xml文件將接收到button當前狀態而且在外觀上作出相應的改變。

1
2
3
4
5
6
<? xml version = "1.0" encoding = "utf-8" ?>
< selector xmlns:android = "http://schemas.android.com/apk/res/android" >
< item android:state_pressed = "true" android:drawable = "@drawable/btn_bg_selected" />
< item android:state_focused = "true" android:drawable = "@drawable/btn_bg" />
< item android:drawable = "@drawable/btn_bg" /> <!-- default -->
</ selector >

  建議22:在Honeycomb以前的版本里時不存在ActionBar跟不少 animation  樣式的,因此可使用ActionBarSherlock 跟NineOldAndroids來代替。Jake Wharton寫的Android開源 組件都是往下兼容的精心傑做。更爲驚喜的是,ABS 擁有強大的功能用來定義ActionBar。

  把速度做爲目標

  建議23:在運行慢的手機上測試。你將在運行慢的手機上發現不少問題,同時它讓你抓狂,沒人會喜歡運行慢的程序。

  建議24:儘可能減小XML佈局層次。更多的層次意味着系統將爲解析你的代碼付出更多的工做,這將會讓圖像渲染的更慢。

  建議25:用Android Lint。在工程目錄上右鍵選擇Eclipse>Android Tools>Run Lint。它將會獲得程序的一些信息,並能提升程序的運行速度,或者它能讓你得代碼更加清爽。

  建議26:Android Lint能夠獲得錯誤信息。它能夠給你的代碼提供很詳細的信息,並在你出錯以前就能夠給作出提示。

  建議27:用<merge>能夠幫助你減小視圖層次結構。這是一種簡單的方式來去除多餘的層次。好的文章都對此有所解釋,並且在 Android Developer中它也顯得不同凡響。

  建議28:用HierarchyViewer能夠直觀的看到你佈局的層次。這個智能的工具能夠顯示佈局中有多少層次,並且能夠提示出那些可讓程序變慢。

  建議29:若是能夠儘可能用RelativeLayoutAbsoluteLayout已通過期了,就不要用了。你常常會遇到在RelativeLayout和LinearLayout中作出選擇的狀況,那就直接用RelativeLayouot吧,由於它可讓你減小視圖層次。好比,你想實現一個以下視圖:

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

  你首先會想到這麼作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
< LinearLayout
android:layout_width=」match_parent」
android:layout_height=」wrap_content」
android:orientation=」horizontal」
>
< TextView
android:text=」Box A takes up left half of the screen」
android:layout_width=」0dip」
android:layout_height=」wrap_content」
android:layout_weight=」1″
/>
< TextView
android:text=」Box B takes up left half of the screen」
android:layout_width=」0dip」
android:layout_height=」wrap_content」
android:layout_weight=」1″
/>
</ LinearLayout >
That works just fine, but you could also use:
< RelativeLayout
android:layout_width=」match_parent」
android:layout_height=」wrap_content」
android:orientation=」horizontal」
>
< TextView
android:text=」Box A takes up left half of the screen」
android:layout_width=」match_parent」
android:layout_height=」wrap_content」
android:layout_toLeftOf=」@+id/dummy_center」
/>
< View
android:id=」@+id/dummy_center」
android:layout_width=」0dip」
android:layout_height=」0dip」
android:layout_gravity=」center」
/>
< TextView
android:text=」Box B takes up left half of the screen」
android:layout_width=」match_parent」
android:layout_height=」wrap_content」
android:layout_toRightOf=」@+id/dummy_center」
/>
</ RelativeLayout >

  第二個表單比第一個難看的多,事實上是至關的糟糕:咱們已經介紹過一個完整的新元素了。可是假如咱們要給每一個盒子裏加入一個圖片,通常的咱們將這樣作:

  盒子 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省空間。

  建議34:若是要用PNG,最好優化一下(用PNGCrush或ImageOptim)
 

  目標bugs

  建議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條寫什麼是了。

相關文章
相關標籤/搜索