1. 程式人生 > >Android最佳實踐之流暢(Seamlessness)設計

Android最佳實踐之流暢(Seamlessness)設計

即使你的應用程式是快速且響應靈敏的,但一些設計仍然會給使用者造成問題——與其它應用程式或對話方塊未事先計劃的互動,意外的資料丟失,意料之外的阻塞等等。避免這些問題,有助於理解應用程式執行的上下文和系統的互動過程,而這些又正影響著你的應用程式。簡而言之,你應該竭盡全力去開發一個與系統和其它應用程式流暢互動的應用程式。

一個常見的流暢問題是,一個應用程式的後臺處理——例如,一個Service或者BroadcastReceiver——彈出一個對話方塊來響應一些事件。這可能看起來沒啥大礙,尤其是你在模擬器上單獨地構建和測試你的應用程式的時候。然而,當你的應用程式執行在真機上時,有可能你的應用程式在沒有獲得使用者焦點時後臺處理顯示了一個對話方塊。因此,可能會出現在活躍的應用程式後方顯示了你的應用程式的對話方塊,或者從當前應用程式奪取焦點顯示了一個對話方塊,而不管當前使用者正在做什麼(例如,正在打電話)。那種行為,對應用程式或使用者來說,就不應該出現。

為了避免這些問題,你的應用程式應該使用合適的系統資源來通知使用者——Notification類。使用Notification,你的應用程式可以在狀態列顯示一個icon來通知使用者已經發生的事情,而不是奪取焦點和打斷使用者。

另一個流暢問題的例子是未能正確實現ActivityonPause()和其它生命週期方法而造成意外丟失了狀態或使用者資料。又或者,如果你的應用程式想暴露資料給其它應用程式使用,你應該通過ContentProvider來暴露,而不是(舉例)通過一個可讀的原始檔案或資料庫來實現。

這些例子的共同點是它們都應該與系統和其它應用程式協作好。Android系統設計時,就把應用程式看作是一堆鬆散耦合的元件,而不是一堆黑盒程式碼。作為開發者來說,允許我們把整個系統看作是更大的元件集合。這有益於我們可以與其它應用程式進行清晰無縫的整合,因此,作為回報,我們應該更好的設計我們的程式碼。

這篇文章將討論常見的流暢問題以及如何避免它們。它將囊括這些主題:

1)     別丟棄資料

2)     不要暴露原始資料

3)     不要打斷使用者

4)     有太多事情要做?線上程裡做

5)     不要讓一個Activity超負荷

6)     擴充套件系統主題

7)     設計你的UI可以應付多螢幕解析度

8)     假設網路很慢

9)     不要假定觸控式螢幕或鍵盤

10)   節省裝置電池

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)節省裝置電池

如果移動裝置經常插在牆上,那麼,它也就不是很“移動”。移動裝置是電池供電的,如果我們能讓每次充電的電池使用得更持久一些,那麼每個人都會更加開心——尤其是使用者。其中兩大耗電硬體是處理器和無線;這也就是我們為什麼要寫儘可能少做工作、儘可能少去使用網路的應用程式的重要原因。

如何讓你的應用程式最小化的佔用處理器,歸根結底還是要寫高效程式碼。為了減少無線的電量消耗,確保對錯誤條件進行正確的處理,並只獲取你要的東西。例如,如果某一個網路操作失敗了,不要不斷地進行重試。如果失敗了一次,有可能是使用者不受歡迎,因此,如果你再以正確的方式操作,有可能還會失敗;所有你做的都是在浪費電池。

使用者是相當聰明的:如果你的程式高耗電,他們是一定會發現的。到那個時點,你唯一可以確定的是,你的程式將很快被解除安裝掉。