即使你的應用程式是快速且響應靈敏的,但一些設計仍然會給使用者造成問題——與其它應用程式或對話方塊未事先計劃的互動,意外的資料丟失,意料之外的阻塞等等。避免這些問題,有助於理解應用程式啟動並執行上下文和系統的互動過程,而這些又正影響著你的應用程式。簡而言之,你應該竭盡全力去開發一個與系統和其它應用程式流程暢互動的應用程式。
一個常見的流暢問題是,一個應用程式的幕後處理——例如,一個 Service或者BroadcastReceiver——彈出一個對話方塊來響應一些事件。這可能看起來沒啥大礙,尤其是你在模擬器上單獨地構建和測試你的應用程式的時候。然而,當你的應用程式運行在真機上時,有可能你的應用程式在沒有獲得使用者焦點時幕後處理顯示了一個對話方塊。因此,可能會出現在活躍的應用程式後方顯示了你的應用程式的對話方塊,或者從當前應用程式奪取焦點顯示了一個對話方塊,而不管目前使用者正在做什麼(例如,正在打電話)。那種行為,對應用程式或使用者來說,就不應該出現。
為了避免這些問題,你的應用程式應該使用合適的系統資源來通知使用者——Notification類。使用Notification,你的應用程式可以在狀態列顯示一個
icon來通知使用者已經發生的事情,而不是奪取焦點和打斷使用者。
另一個流暢問題的例子是未能正確實現Activity的 onPause()和其它生命週期方法而造成意外丟失了狀態或使用者資料。又或者,如果你的應用程式想暴露資料給其它應用程式使用,你應該通過ContentProvider來暴露,而不是(舉例)通過一個可讀的原始檔案或資料庫來實現。
這些例子的共同點是它們都應該與系統和其它應用程式協作好。Android系統設計時,就把應用程式看作是一堆鬆散耦合的組件,而不是一堆黑盒代碼。作為開發人員來說,允許我們把整個系統看作是更大的組件集合。這有益於我們可以與其它應用程式進行清晰無縫的整合,因此,作為回報,我們應該更好的設計我們的代碼。
下面將討論常見的流暢問題以及如何避免它們:
1)別丟棄資料
一定要記住Android是一個移動平台。可以顯而易見地說,其它Activity(例如,“Incoming Phone Call”應用程式)可能會在任何時候彈出來遮蓋你的Activity,記住這個事實很重要。因為這個過程將觸發onSaveInstanceState()和 onPause()方法,並可能導致你的應用程式被殺死。
如果使用者在你的應用程式中正在編輯資料時,其它 Activity出現了,這時,你的應用程式被殺死時可能丟失那些資料。當然了,除非你事先儲存了進行中的工作。“Android方式”是這樣做的:能接收和編輯使用者輸入的 Android應用程式應該重寫 onSaveInstanceState()方法,並以恰當的方式儲存它們的狀態。當使用者重新訪問應用程式時,她能得到她的資料。
進行這種處理方式最經典的例子是 mail應用程式。如果使用者正在輸入 email,這時其它 Activity啟動了,mail應用程式應該把正在編輯的email以草稿的方式儲存起來。
2)不要暴露未經處理資料
如果你不想穿著內衣在大街上溜達的話,你的資料也不應該這樣。儘管可能存在暴露應用程式的某種形式給其它應用程式,但這通常不是最好的主意。暴露未經處理資料,要求其它應用程式能夠理解你的資料的格式;如果你變更了格式,那麼,你將破壞那些沒有進行同步更新的應用程式。
“Android方式”是建立一個 ContentProvider,以一種清晰的、深思熟慮的和可維護的API方式暴露你的資料給其它應用程式。使用 ContentProvider,就好像是插入Java介面來分離和組裝兩片高耦合的代碼。這意味著你可以修改資料的內部格式,而不用修改由ContentProvider暴露的介面,這樣,也不會影響其它應用程式。
3)不要打斷使用者
如果使用者正在運行一個應用程式(例如,Phone程式),斷定對使用者操作的目的才是安全的。這也就是為什麼必須避免建立Activity,而是直接在當前的 Activity中響應使用者的輸入。
那就是說,不要在 BroadcastReceiver或在後台啟動並執行 Service中調用 callActivity()。這麼做會中斷當前啟動並執行應用程式,並導致使用者惱怒。也許更糟糕的是,你的 Activity可能成為“按鍵強盜”,竊取了使用者要提供給前一個 Activity的輸入。視乎你的應用程式所做的事情,這可能是個壞訊息。
不選擇在後台直接建立 Activity UI,取而代之的是,應該使用NotificationManager來設定 Notification。它們會出現在狀態列,並且使用者可以在他閒置時候點擊它們,來查看你的應用程式向他顯示了什麼。(注意,如果你的 Activity已經在前台了,以上將不適用:這時,對於使用者的輸入,使用者期望的是看到下一個 Activity來響應)
4)有太多事情要做?線上程裡做
如果你的應用程式需要執行一些昂貴或耗時的計算的話,你應該儘可能地將它挪到線程裡。這將阻止向使用者顯示可怕的“Application Not Responding”對話方塊,如果不這樣做,最終的結果會導致你的應用程式完全終止。
一般情況下,Activity中的所有代碼,包括它的 View,都運行在相同的線程裡。在這個線程裡,還需要處理UI事件。例如,當使用者按下一個按鍵,一個 key-down事件就會添加到 Activity的主線程隊列裡。事件處理系統需要很快讓這個事件出列並得到處理;如果沒有,系統數秒後會認為應用程式已經掛起並為使用者提供殺死應用程式的機會。
如果有耗時的代碼,內聯在Activity上運行也就是運行在事件處理線程裡,這在很大程度上阻塞了事件處理。這會延遲輸入處理,並導致ANR對話方塊。為了避免這個,把你的計算移到線程裡。
5)不要讓一個
Activity超負荷
任何值得使用的應用程式都可能有幾個不同的螢幕。當設計UI螢幕時,請一定要使用多個Activity對象執行個體。 依賴於你的開發背景,你可能理解 Activity類似於 Java Applet,它是你應用程式的進入點。然而,那並不精確:Applet子類是一個 Java Applet的單一進入點,而一個Activity應該看作是你的應用程式多個潛在進入點之一。你的“main”Activity和其它之間的唯一不同點是“main”Activity正巧是在AndroidManifest.xml檔案中唯一對“android.
intent.action.MAIN”動作感興趣的Activity。 因此,當設計你的應用程式的時候,把你的應用程式看作是Activity對象的集合。從長遠來看,這會使得你的代碼更加方便維護。
6)擴充系統主題
當談到 UI觀感時,巧妙地交融非常重要。使用者在使用與自己期望相反的 UI的應用程式時,會產生不愉快的感覺。當設計你的 UI時,你應該盡量避免太多自己的主題。相反的,使用同一個主題。你可以重寫或擴充你需要的主題部分,但至少在與其它應用程式相同的 UI基礎上開始。
7)設計你的
UI可以應對多螢幕解析度
不同的 Android裝置可能支援不同的螢幕解析度。甚至一些可以自己變更解析度,例如,切換到風景模式。確保你的布局和圖片能足夠靈活地在不同的裝置螢幕上正常顯示。幸運的是,這很容易做到。簡而言之,你需要做的是為主要解析度提供不同版本的作品,然後為不同的尺寸設計你的布局。(例如,避免使用寫入程式碼位置而使用相對布局。)如果那樣做的話,系統會處理剩下的部分,而且你的應用程式在任何裝置上都看起來很棒。
8)假設網路很慢
Android裝置會有多種網路連接選項。所有的都提供資料訪問,但之間肯定有更快的。其中,速度最慢的是GPRS,GSM網路的非 3G資料服務。即使具備 3G能力的裝置在非3G的網路上也會花費很多的時間,所以,網路很慢仍然是一個長期存在的事實。
這就是為什麼你應該按照最小化的網路訪問和頻寬來編寫你的代碼。你不能假設網路是快速的,所以,你應該總是計劃它是慢的。如果你的使用者碰巧在一個快速的網路上,那很好——他們的使用者體驗會提升。你要避免相反的情形:在不同的地點和不同時間,應用程式有時可用,有時慢得令人抓狂,這樣的程式可能不會受歡迎。
還有一個潛在的地方是,如果你正在使用模擬器,那麼你很容易受它迷糊,因為模擬器使用電腦的網路連接。這比行動電話通訊快很多,所以,你需要修改模擬器設定來類比較低的網路速度。你可以在 Eclipse中做到這點,在啟動選項的模擬器設定頁裡設定或者在啟動模擬器時通過命令列選項設定。
9)不要假定觸控螢幕或鍵盤
Android可以支援多種外觀形狀。也就是說,一些Android裝置擁有全“QWERTY”鍵盤,而其它可能會有40鍵、12鍵或其它鍵盤設定。同樣的,一些裝置可能有觸控螢幕,但一些也會沒有。當建立你的應用程式的時候,記住這一點。不要假定特定的鍵盤配置——除非你真的想限定你的應用程式只運行在某些裝置上。
10)節省裝置電池
如果行動裝置經常插在牆上,那麼,它也就不是很“移動”。行動裝置是電池供電的,如果我們能讓每次充電的電池使用得更持久一些,那麼每個人都會更加開心——尤其是使用者。其中兩大耗電硬體是處理器和無線;這也就是我們為什麼要寫儘可能少做工作、儘可能少去使用網路的應用程式的重要原因。
如何讓你的應用程式最小化的佔用處理器,歸根結底還是要寫高效代碼。為了減少無線電量消耗,確保對錯誤條件進行正確的處理,並只擷取你要的東西。例如,如果某一個網路操作失敗了,不要不斷地進行重試。如果失敗了一次,有可能是使用者不受歡迎,因此,如果你再以正確的方式操作,有可能還會失敗;所有你做的都是在浪費電池。
使用者是相當聰明的:如果你的程式高耗電,他們是一定會發現的。到那個時點,你唯一可以確定的是,你的程式將很快被卸載掉。