默認(rèn)分類2010-11-17 09:53:22閱讀8評論0 字號:大中小 訂閱
即使你的應(yīng)用程序是快速且響應(yīng)靈敏的,但一些設(shè)計(jì)仍然會給用戶造成問題——與其它應(yīng)用程序或?qū)υ捒蛭词孪扔?jì)劃的交互,意外的數(shù)據(jù)丟失,意料之外的阻塞等等。避免這些問題,有助于理解應(yīng)用程序運(yùn)行的上下文和系統(tǒng)的交互過程,而這些又正影響著你的應(yīng)用程序。簡而言之,你應(yīng)該竭盡全力去開發(fā)一個與系統(tǒng)和其它應(yīng)用程序流暢交互的應(yīng)用程序。
一個常見的流暢問題是,一個應(yīng)用程序的后臺處理——例如,一個Service或者BroadcastReceiver——彈出一個對話框來響應(yīng)一些事件。這可能看起來沒啥大礙,尤其是你在模擬器上單獨(dú)地構(gòu)建和測試你的應(yīng)用程序的時候。然而,當(dāng)你的應(yīng)用程序運(yùn)行在真機(jī)上時,有可能你的應(yīng)用程序在沒有獲得用戶焦點(diǎn)時后臺處理顯示了一個對話框。因此,可能會出現(xiàn)在活躍的應(yīng)用程序后方顯示了你的應(yīng)用程序的對話框,或者從當(dāng)前應(yīng)用程序奪取焦點(diǎn)顯示了一個對話框,而不管當(dāng)前用戶正在做什么(例如,正在打電話)。那種行為,對應(yīng)用程序或用戶來說,就不應(yīng)該出現(xiàn)。
為了避免這些問題,你的應(yīng)用程序應(yīng)該使用合適的系統(tǒng)資源來通知用戶——Notification類。使用Notification,你的應(yīng)用程序可以在狀態(tài)欄顯示一個icon來通知用戶已經(jīng)發(fā)生的事情,而不是奪取焦點(diǎn)和打斷用戶。
另一個流暢問題的例子是未能正確實(shí)現(xiàn)Activity的onPause()和其它生命周期方法而造成意外丟失了狀態(tài)或用戶數(shù)據(jù)。又或者,如果你的應(yīng)用程序想暴露數(shù)據(jù)給其它應(yīng)用程序使用,你應(yīng)該通過ContentProvider來暴露,而不是(舉例)通過一個可讀的原始文件或數(shù)據(jù)庫來實(shí)現(xiàn)。
這些例子的共同點(diǎn)是它們都應(yīng)該與系統(tǒng)和其它應(yīng)用程序協(xié)作好。Android系統(tǒng)設(shè)計(jì)時,就把應(yīng)用程序看作是一堆松散耦合的組件,而不是一堆黑盒代碼。作為開發(fā)者來說,允許我們把整個系統(tǒng)看作是更大的組件集合。這有益于我們可以與其它應(yīng)用程序進(jìn)行清晰無縫的集成,因此,作為回報(bào),我們應(yīng)該更好的設(shè)計(jì)我們的代碼。
這篇文章將討論常見的流暢問題以及如何避免它們。它將囊括這些主題:
1) 別丟棄數(shù)據(jù)
2) 不要暴露原始數(shù)據(jù)
3) 不要打斷用戶
4) 有太多事情要做?在線程里做
5) 不要讓一個Activity超負(fù)荷
6) 擴(kuò)展系統(tǒng)主題
7) 設(shè)計(jì)你的UI可以應(yīng)付多屏幕分辨率
8) 假設(shè)網(wǎng)絡(luò)很慢
9) 不要假定觸摸屏或鍵盤
10) 節(jié)省設(shè)備電池
1)別丟棄數(shù)據(jù)
一定要記住Android是一個移動平臺。可以顯而易見地說,其它Activity(例如,“Incoming Phone Call”應(yīng)用程序)可能會在任何時候彈出來遮蓋你的Activity,記住這個事實(shí)很重要。因?yàn)檫@個過程將觸發(fā)onSaveInstanceState()和onPause()方法,并可能導(dǎo)致你的應(yīng)用程序被殺死。
如果用戶在你的應(yīng)用程序中正在編輯數(shù)據(jù)時,其它Activity出現(xiàn)了,這時,你的應(yīng)用程序被殺死時可能丟失那些數(shù)據(jù)。當(dāng)然了,除非你事先保存了正在進(jìn)行的工作。“Android方式”是這樣做的:能接收和編輯用戶輸入的Android應(yīng)用程序應(yīng)該重寫onSaveInstanceState()方法,并以恰當(dāng)?shù)姆绞奖4嫠鼈兊臓顟B(tài)。當(dāng)用戶重新訪問應(yīng)用程序時,她能得到她的數(shù)據(jù)。
進(jìn)行這種處理方式最經(jīng)典的例子是mail應(yīng)用程序。如果用戶正在輸入email,這時其它Activity啟動了,mail應(yīng)用程序應(yīng)該把正在編輯的email以草稿的方式保存起來。
2)不要暴露原始數(shù)據(jù)
如果你不想穿著內(nèi)衣在大街上溜達(dá)的話,你的數(shù)據(jù)也不應(yīng)該這樣。盡管可能存在暴露應(yīng)用程序的某種形式給其它應(yīng)用程序,但這通常不是最好的主意。暴露原始數(shù)據(jù),要求其它應(yīng)用程序能夠理解你的數(shù)據(jù)的格式;如果你變更了格式,那么,你將破壞那些沒有進(jìn)行同步更新的應(yīng)用程序。
“Android方式”是創(chuàng)建一個ContentProvider,以一種清晰的、深思熟慮的和可維護(hù)的API方式暴露你的數(shù)據(jù)給其它應(yīng)用程序。使用ContentProvider,就好像是插入Java接口來分離和組裝兩片高耦合的代碼。這意味著你可以修改數(shù)據(jù)的內(nèi)部格式,而不用修改由ContentProvider暴露的接口,這樣,也不會影響其它應(yīng)用程序。
3)不要打斷用戶
如果用戶正在運(yùn)行一個應(yīng)用程序(例如,Phone程序),斷定對用戶操作的目的才是安全的。這也就是為什么必須避免創(chuàng)建Activity,而是直接在當(dāng)前的Activity中響應(yīng)用戶的輸入。
那就是說,不要在BroadcastReceiver或在后臺運(yùn)行的Service中調(diào)用callActivity()。這么做會中斷當(dāng)前運(yùn)行的應(yīng)用程序,并導(dǎo)致用戶惱怒。也許更糟糕的是,你的Activity可能成為“按鍵強(qiáng)盜”,竊取了用戶要提供給前一個Activity的輸入。視乎你的應(yīng)用程序所做的事情,這可能是個壞消息。
不選擇在后臺直接創(chuàng)建Activity UI,取而代之的是,應(yīng)該使用NotificationManager來設(shè)置Notification。它們會出現(xiàn)在狀態(tài)欄,并且用戶可以在他空閑的時候點(diǎn)擊它們,來查看你的應(yīng)用程序向他顯示了什么。
(注意,如果你的Activity已經(jīng)在前臺了,以上將不適用:這時,對于用戶的輸入,用戶期望的是看到下一個Activity來響應(yīng)。)
4)有太多事情要做?在線程里做
如果你的應(yīng)用程序需要執(zhí)行一些昂貴或耗時的計(jì)算的話,你應(yīng)該盡可能地將它挪到線程里。這將阻止向用戶顯示可怕的“Application Not Responding”對話框,如果不這樣做,最終的結(jié)果會導(dǎo)致你的應(yīng)用程序完全終止。
一般情況下,Activity中的所有代碼,包括它的View,都運(yùn)行在相同的線程里。在這個線程里,還需要處理UI事件。例如,當(dāng)用戶按下一個按鍵,一個key-down事件就會添加到Activity的主線程隊(duì)列里。事件處理系統(tǒng)需要很快讓這個事件出列并得到處理;如果沒有,系統(tǒng)數(shù)秒后會認(rèn)為應(yīng)用程序已經(jīng)掛起并為用戶提供殺死應(yīng)用程序的機(jī)會。
如果有耗時的代碼,內(nèi)聯(lián)在Activity上運(yùn)行也就是運(yùn)行在事件處理線程里,這在很大程度上阻塞了事件處理。這會延遲輸入處理,并導(dǎo)致ANR對話框。為了避免這個,把你的計(jì)算移到線程里。在響應(yīng)靈敏性設(shè)計(jì)的文章里已經(jīng)討論了如何做。
5)不要讓一個Activity超負(fù)荷
任何值得使用的應(yīng)用程序都可能有幾個不同的屏幕。當(dāng)設(shè)計(jì)UI屏幕時,請一定要使用多個Activity對象實(shí)例。
依賴于你的開發(fā)背景,你可能理解Activity類似于Java Applet,它是你應(yīng)用程序的入口點(diǎn)。然而,那并不精確:Applet子類是一個Java Applet的單一入口點(diǎn),而一個Activity應(yīng)該看作是你的應(yīng)用程序多個潛在入口點(diǎn)之一。你的“main”Activity和其它之間的唯一不同點(diǎn)是“main”Activity正巧是在AndroidManifest.xml文件中唯一對“android.intent.action.MAIN”動作感興趣的Activity。
因此,當(dāng)設(shè)計(jì)你的應(yīng)用程序的時候,把你的應(yīng)用程序看作是Activity對象的集合。從長遠(yuǎn)來看,這會使得你的代碼更加方便維護(hù)。
6)擴(kuò)展系統(tǒng)主題
當(dāng)談到UI觀感時,巧妙地交融非常重要。用戶在使用與自己期望相反的UI的應(yīng)用程序時,會產(chǎn)生不愉快的感覺。當(dāng)設(shè)計(jì)你的UI時,你應(yīng)該盡量避免太多自己的主題。相反的,使用同一個主題。你可以重寫或擴(kuò)展你需要的主題部分,但至少在與其它應(yīng)用程序相同的UI基礎(chǔ)上開始。詳細(xì)請參照“應(yīng)用風(fēng)格和主題”部分。
7)設(shè)計(jì)你的UI可以應(yīng)對多屏幕分辨率
不同的Android設(shè)備可能支持不同的屏幕分辨率。甚至一些可以自己變更分辨率,例如,切換到風(fēng)景模式。確保你的布局和圖片能足夠靈活地在不同的設(shè)備屏幕上正常顯示。
幸運(yùn)的是,這很容易做到。簡而言之,你需要做的是為主要分辨率提供不同版本的作品,然后為不同的尺寸設(shè)計(jì)你的布局。(例如,避免使用硬編碼位置而使用相對布局。)如果那樣做的話,系統(tǒng)會處理剩下的部分,而且你的應(yīng)用程序在任何設(shè)備上都看起來很棒。
8)假設(shè)網(wǎng)絡(luò)很慢
Android設(shè)備會有多種網(wǎng)絡(luò)連接選項(xiàng)。所有的都提供數(shù)據(jù)訪問,但之間肯定有更快的。其中,速度最慢的是GPRS,GSM網(wǎng)絡(luò)的非3G數(shù)據(jù)服務(wù)。即使具備3G能力的設(shè)備在非3G的網(wǎng)絡(luò)上也會花費(fèi)很多的時間,所以,網(wǎng)絡(luò)很慢仍然是一個長期存在的事實(shí)。
這就是為什么你應(yīng)該按照最小化的網(wǎng)絡(luò)訪問和帶寬來編寫你的代碼。你不能假設(shè)網(wǎng)絡(luò)是快速的,所以,你應(yīng)該總是計(jì)劃它是慢的。如果你的用戶碰巧在一個快速的網(wǎng)絡(luò)上,那很好——他們的用戶體驗(yàn)會提升。你要避免相反的情形:在不同的地點(diǎn)和不同時間,應(yīng)用程序有時可用,有時慢得令人抓狂,這樣的程序可能不會受歡迎。
還有一個潛在的地方是,如果你正在使用模擬器,那么你很容易受它迷糊,因?yàn)槟M器使用電腦的網(wǎng)絡(luò)連接。這比手機(jī)網(wǎng)絡(luò)快很多,所以,你需要修改模擬器設(shè)定來模擬較低的網(wǎng)絡(luò)速度。你可以在Eclipse中做到這點(diǎn),在啟動選項(xiàng)的模擬器設(shè)置頁里設(shè)置或者在啟動模擬器時通過命令行選項(xiàng)設(shè)置。
9)不要假定觸摸屏或鍵盤
Android可以支持多種外觀形狀。也就是說,一些Android設(shè)備擁有全“QWERTY”鍵盤,而其它可能會有40鍵、12鍵或其它鍵盤設(shè)置。同樣的,一些設(shè)備可能有觸摸屏,但一些也會沒有。
當(dāng)創(chuàng)建你的應(yīng)用程序的時候,記住這一點(diǎn)。不要假定特定的鍵盤布局——除非你真的想限定你的應(yīng)用程序只運(yùn)行在某些設(shè)備上。
10)節(jié)省設(shè)備電池
如果移動設(shè)備經(jīng)常插在墻上,那么,它也就不是很“移動”。移動設(shè)備是電池供電的,如果我們能讓每次充電的電池使用得更持久一些,那么每個人都會更加開心——尤其是用戶。其中兩大耗電硬件是處理器和無線;這也就是我們?yōu)槭裁匆獙懕M可能少做工作、盡可能少去使用網(wǎng)絡(luò)的應(yīng)用程序的重要原因。
如何讓你的應(yīng)用程序最小化的占用處理器,歸根結(jié)底還是要寫高效代碼。為了減少無線的電量消耗,確保對錯誤條件進(jìn)行正確的處理,并只獲取你要的東西。例如,如果某一個網(wǎng)絡(luò)操作失敗了,不要不斷地進(jìn)行重試。如果失敗了一次,有可能是用戶不受歡迎,因此,如果你再以正確的方式操作,有可能還會失??;所有你做的都是在浪費(fèi)電池。
用戶是相當(dāng)聰明的:如果你的程序高耗電,他們是一定會發(fā)現(xiàn)的。到那個時點(diǎn),你唯一可以確定的是,你的程序?qū)⒑芸毂恍遁d掉。