用戶體驗(yàn)導(dǎo)向的Android應(yīng)用開發(fā)

2011-11-14 14:01:52來(lái)源:《程序員》雜志作者:陳彧堃

Android開發(fā)目前是移動(dòng)開發(fā)中的“當(dāng)紅炸子雞”,大量Java程序員涌向Android,同時(shí)會(huì)習(xí)慣性地將桌面和Web端的開發(fā)/設(shè)計(jì)經(jīng)驗(yàn)帶到移動(dòng)設(shè)備上。

本文指出“流暢的環(huán)境”、“友好的體驗(yàn)”和“節(jié)省電量”是保證Android應(yīng)用擁有良好用戶體驗(yàn)的三要素。

Android開發(fā)目前是移動(dòng)開發(fā)中的“當(dāng)紅炸子雞”,大量Java程序員涌向Android,同時(shí)會(huì)習(xí)慣性地將桌面和Web端的開發(fā)/設(shè)計(jì)經(jīng)驗(yàn)帶到移動(dòng)設(shè)備上。這樣的好處是充分利用了移動(dòng)開發(fā)和桌面/Web服務(wù)的共性,比如廣泛使用的列表、本地?cái)?shù)據(jù)庫(kù)等常用組件;壞處是移動(dòng)和桌面/Web的使用場(chǎng)景和載體完全不同,直接移植桌面端開發(fā)的經(jīng)驗(yàn)有害無(wú)益。

比如,手機(jī)主要在碎片時(shí)間使用,用戶容易對(duì)復(fù)雜的界面設(shè)計(jì)感到疲憊;同時(shí),移動(dòng)環(huán)境中上網(wǎng)慢,網(wǎng)絡(luò)連接頻率和失敗重發(fā)機(jī)制的設(shè)計(jì)更有講究;此外,手機(jī)電池續(xù)航能力差,后臺(tái)復(fù)雜的計(jì)算會(huì)加速耗電速度。這些開發(fā)理念直接影響用戶最終體驗(yàn),下面我們來(lái)討論一下在Android中如何以用戶體驗(yàn)為導(dǎo)向進(jìn)行開發(fā)優(yōu)化。

雖然不用深入了解底層,但需要對(duì)系統(tǒng)有基本的了解。Android系統(tǒng)分層清晰,最底層是Linux Kernel 2.6,之上包含了Webkit、SQLite、OpenGL ES等基礎(chǔ)C/C++庫(kù),同時(shí)Dalvik虛擬機(jī)運(yùn)行于Kernel之上,幫助應(yīng)用進(jìn)行底層內(nèi)存管理(這樣使Android應(yīng)用無(wú)法直接進(jìn)行內(nèi)存釋放)。這些庫(kù)一方面被系統(tǒng)大量使用,另一方面也通過Framework層提供接口給開發(fā)者。此外,F(xiàn)ramework層還提供其他系統(tǒng)級(jí)的服務(wù),如消息通知服務(wù)、位置獲取服務(wù)、設(shè)備信息讀取服務(wù)等。

由此可見Android對(duì)于開發(fā)者非常開放和靈活,盡管如此,開發(fā)時(shí)仍然要注意不要過于隨意,以免產(chǎn)品過于復(fù)雜而讓用戶不知所措。當(dāng)然,除了少數(shù)系統(tǒng)級(jí)應(yīng)用開發(fā)需要深入了解Framework層實(shí)現(xiàn)機(jī)制之外,一般第三方應(yīng)用開發(fā)者并不需要深入了解每一層原理,應(yīng)把重點(diǎn)放在如何理解和靈活運(yùn)用龐大的 Android SDK API。

本文主要圍繞用戶的三種感覺來(lái)說明如何進(jìn)行開發(fā)。

流暢的環(huán)境

讓用戶感覺使用非常流暢。遲緩會(huì)潛移默化地留下不好的印象。用戶看見App的圖標(biāo),便會(huì)在心中和“遲緩”、“卡”、“不穩(wěn)定”畫上等號(hào),產(chǎn)生“打開畏懼癥”。

用戶滑動(dòng)Listview、Gallery、Coverflow時(shí)覺得卡,多半是因?yàn)橄鄳?yīng)Adapter對(duì)getView的處理不夠好。每個(gè)Item都會(huì)和數(shù)據(jù)源綁定,而數(shù)據(jù)源的獲取方式有多種:網(wǎng)絡(luò)、本地文件、SQLite數(shù)據(jù)庫(kù)、SharedPreference以及內(nèi)存,它們的傳輸時(shí)間分別是7秒、 2秒、1秒、100毫秒、5毫秒。

對(duì)于最耗時(shí)的網(wǎng)絡(luò)請(qǐng)求,很多人會(huì)采用異步操作,不會(huì)讓用戶耗費(fèi)精力在網(wǎng)絡(luò)等待過程中。但在I/O以及SQLite查詢時(shí),用戶的等待時(shí)間容易被忽略,從而降低滑動(dòng)的流暢感。Android用戶常常遇到的ANR(Application Not Responding),便是這個(gè)問題的升級(jí)版。要知道,Activity Manager和Window Manager監(jiān)視著應(yīng)用程序的響應(yīng),當(dāng)發(fā)現(xiàn)按鍵或觸摸發(fā)生后5秒還沒執(zhí)行完處理邏輯,或是BroadcastReceiver處理時(shí)間超過了10秒,系統(tǒng)便會(huì)拋出ANR錯(cuò)誤,并提醒用戶強(qiáng)制終止應(yīng)用。

我的建議如下:

    * 對(duì)于無(wú)法在短時(shí)間完成的操作,在獨(dú)立線程中處理,Android有多種異步處理模型可供使用,包括Thread-Handler、AsyncTask以及Loader and CursorLoader。

    * 盡可能減少?gòu)?fù)雜計(jì)算和降低I/O,充分估計(jì)對(duì)象的使用頻率,選擇合適的數(shù)據(jù)源。個(gè)人認(rèn)為大部分應(yīng)用中不會(huì)存在太多太大的對(duì)象,可以考慮將數(shù)據(jù)緩存在內(nèi)存中。如果應(yīng)用中有太多圖片不能一直緩存,可采用LRU(Least Recently Used ,最近最少使用)算法將不常用的緩存清理出內(nèi)存,這樣緩存大小可控,從而不會(huì)出現(xiàn)Out of Memory(內(nèi)存溢出)的Bug。

但要注意,算法是把雙刃劍,如果你享受到類似LRU帶來(lái)的提速后的爽快,就可能會(huì)挖空心思探索更高效的算法。這時(shí)要慎重,后面會(huì)講到看上去很牛的算法帶來(lái)的問題。

另外,網(wǎng)絡(luò)等待雖然是最耗時(shí),但卻容易被忽略。因?yàn)榇挚瓷先ゾW(wǎng)絡(luò)是不可控的,與開發(fā)無(wú)關(guān)。一般會(huì)設(shè)置幾秒鐘的超時(shí),超時(shí)則重發(fā)。事實(shí)上,在國(guó)內(nèi),中國(guó)移動(dòng)的GRPS網(wǎng)絡(luò)占主導(dǎo),所以手機(jī)上網(wǎng)普遍很慢,HTTP連接上下行10秒是很正常的,超時(shí)設(shè)置20秒都不為過。同時(shí),根據(jù)友盟對(duì)Android應(yīng)用使用的統(tǒng)計(jì),用戶在每個(gè)App上的一次啟動(dòng)花費(fèi)時(shí)間是1分鐘左右,理論上有3次重發(fā)機(jī)會(huì),但一次超時(shí)(假設(shè)是20秒)后,用戶就已經(jīng)失去信心,不會(huì)再等待一次了。所以在開發(fā)時(shí),要結(jié)合具體使用場(chǎng)景,設(shè)計(jì)數(shù)據(jù)預(yù)取機(jī)制,盡量降低網(wǎng)絡(luò)請(qǐng)求次數(shù),同時(shí)考慮gzip、protobuf等數(shù)據(jù)壓縮和編碼機(jī)制,保證一次取到的數(shù)據(jù)不至于太大而造成額外延時(shí)。

\
Android架構(gòu)圖

友好的體驗(yàn)

不友好的體驗(yàn)來(lái)自三個(gè)方面。

其一是Android的碎片化帶來(lái)了UI適配問題。Android 機(jī)型眾多,和iPhone相比,界面適配飽受詬病。要保證應(yīng)用能運(yùn)行在不同分辨率的手機(jī)上,需要理解Android提供的自動(dòng)適配方案。事實(shí)上,Android系統(tǒng)為UI適配做了充分的考慮,只要理解系統(tǒng)對(duì)此的精心設(shè)計(jì),就能在開發(fā)時(shí)少走很多彎路,給不同分辨率的用戶提供友好的呈現(xiàn)界面。
簡(jiǎn)單來(lái)說可做如下解釋:

    * 開發(fā)時(shí)避免絕對(duì)布局(AbsoluteLayout),因?yàn)檫@會(huì)讓你的應(yīng)用只在測(cè)試機(jī)上“看上去很美”,放到別處就橫七豎八。

    * 界面控件大小單位多用DIP(Device Independent Pixels),理由同上。

    * 圖片盡量使用系統(tǒng)提供的NinePatch技術(shù),能使同一張小圖片在不同分辨率的屏幕上保持精度自由縮放。

其二是濫用通知服務(wù),導(dǎo)致用戶很容易被打斷。典型場(chǎng)景是在通知欄上的各種通知消息,有關(guān)無(wú)關(guān)的都推送,讓用戶感覺不適。建議是通知適可而止,除非是對(duì)用戶真正有用的信息,否則最好讓用戶進(jìn)入程序后再提示。

其三是主要來(lái)自設(shè)計(jì)師的問題,就是照搬iPhone應(yīng)用的設(shè)計(jì)。Android的系統(tǒng)特點(diǎn)不同于iPhone,如程序的棧式管理機(jī)制、菜單按鈕、返回按鈕,從而用戶的預(yù)期也不盡相同。比如我發(fā)現(xiàn)很多設(shè)計(jì)師喜歡拋棄返回鍵,模仿iPhone給每一頁(yè)設(shè)計(jì)一個(gè)軟返回按鈕。生硬做作的移植會(huì)導(dǎo)致與用戶預(yù)期不一致,是徹底的設(shè)計(jì)敗筆。

節(jié)省電量

隨時(shí)都得插在墻上充電的設(shè)備,不叫移動(dòng)設(shè)備。如果你的App讓用戶一直守著墻角,用戶也會(huì)很快把你丟到墻角。你會(huì)問:“他怎么知道我的應(yīng)用耗電?”很抱歉,目前來(lái)看,Android用戶中有大量發(fā)燒友和技術(shù)高手,同時(shí)系統(tǒng)很不客氣地記錄了每個(gè)應(yīng)用的耗電量,于是用戶偶爾會(huì)去系統(tǒng)后臺(tái)查查耗電大戶,之后會(huì)毫不客氣地打開卸載工具。

所以需注意以下幾點(diǎn):

第一,不要絞盡腦汁設(shè)計(jì)復(fù)雜算法,不要在后臺(tái)跑服務(wù),不要網(wǎng)斷了還不停重試。在開發(fā)一個(gè)模塊前先想想會(huì)不會(huì)費(fèi)電,如果會(huì),就不要去做。代碼是為了服務(wù)用戶,而不是折騰用戶。

高手喜歡挑戰(zhàn),尤其在手機(jī)上實(shí)現(xiàn)精巧的算法,這樣能帶來(lái)更強(qiáng)的征服感。有人曾在手機(jī)上實(shí)現(xiàn)了布隆過濾器(一個(gè)龐大精巧的類哈希表,多用于在服務(wù)器端如垃圾郵件查找),其內(nèi)存消耗和計(jì)算復(fù)雜度都遠(yuǎn)遠(yuǎn)高于普通的HashMap,且實(shí)現(xiàn)并不容易。結(jié)果App發(fā)布之后,出現(xiàn)用戶抱怨耗電量大,并且經(jīng)常出現(xiàn)Bug,最后還是老老實(shí)實(shí)換成了HashMap。任何算法的目的都是為了服務(wù)用戶,如果簡(jiǎn)單自然的方法能更好地做到這點(diǎn),何樂而不為?如果真的在客戶端找不到簡(jiǎn)單的算法,則需要反思——為什么在手機(jī)上需要復(fù)雜的計(jì)算?是否該將這些計(jì)算放在服務(wù)器端?

第二,不要在后臺(tái)濫用Service。Android非常開放,開發(fā)者可在后臺(tái)觸發(fā)任何處理邏輯,肆意占用CPU和內(nèi)存。一般來(lái)說,Service的目的是為了監(jiān)控變化,包括系統(tǒng)和網(wǎng)絡(luò)變化。系統(tǒng)變化可通過注冊(cè)BroadcastReceiver監(jiān)聽控制,比如應(yīng)用安裝和卸載等事件,這樣耗電量非常小,完全可替代在Service中輪播。網(wǎng)絡(luò)請(qǐng)求無(wú)法用BroadcastReceiver監(jiān)聽,但是有兩個(gè)建議。

    * 無(wú)嚴(yán)苛的實(shí)時(shí)性要求,可延長(zhǎng)輪播間隔,如6小時(shí)自動(dòng)請(qǐng)求一次,同時(shí)時(shí)間隔可通過服務(wù)器在線更新。這樣既省電,偶爾急需實(shí)時(shí)推送時(shí)也可在線調(diào)整時(shí)間間隔。

    * 對(duì)實(shí)時(shí)性有要求,考慮使用成熟的推送服務(wù),如Google的C2DM(http://code.google.com/Android/c2dm/),和亞馬遜的AWS SDK (http://aws.amazon.com/sdkforAndroid/)。

第三,網(wǎng)絡(luò)請(qǐng)求不要太頻繁。系統(tǒng)組件中最耗電的是屏幕,其次就是網(wǎng)絡(luò)。前文已經(jīng)提到過,網(wǎng)絡(luò)出錯(cuò)重發(fā)會(huì)降低用戶體驗(yàn),還會(huì)耗費(fèi)電力?赏ㄟ^數(shù)據(jù)預(yù)取結(jié)合數(shù)據(jù)壓縮算法減少網(wǎng)絡(luò)請(qǐng)求次數(shù)。

總之,在開發(fā)時(shí)我們要替用戶思考是否做到了“流暢、友好、省電”,以保證App擁有不錯(cuò)的用戶體驗(yàn)。

作者陳彧堃,曾任職于微軟研究院,從事數(shù)據(jù)挖掘及機(jī)器學(xué)習(xí)的相關(guān)研究,對(duì)時(shí)空數(shù)據(jù)挖掘,普適計(jì)算等領(lǐng)域有深入了解。2010年4月加入友盟,開始打造友盟移動(dòng)開發(fā)平臺(tái)。

關(guān)鍵詞:Android開發(fā)