從財富幫項目啟動到現在也半年多了,開發(fā)過程中零零散散地也積累了一些經驗心得,今天把財富幫iOS客戶端的一些設計思路跟大家分享一下,權當拋磚引玉。因為分享的是思路而不涉及具體實現細節(jié),所以也同樣適用于Android哦。
Debug頁面
一個好的App除了實現正常的功能外,還應該有一個良好的debug機制。這個Debug機制應該用一個隱藏的不易被普通用戶發(fā)現的方式去實現,值得慶幸的是iOS和Android系統(tǒng)都提供了Url Scheme技術,用來從外界打開App的一個具體頁面。
財富幫目前的Debug頁面對一些不易在運行時調試的功能添加了輔助功能,比如推送。對于推送,我們設定了推送日志,用來收集服務器推送過來的信息。分析這些消息可以幫助我們精準的分析出問題到底出自服務器端還是客戶端甚至問題的具體原因。另外,對于推送我們還設定了賬號綁定機制,這個綁定于設備的賬號主要被用來做單推測試。單推測試是推送測試中很重要的一個環(huán)節(jié),一般情況下只要單推測試過了,群推就是n個單推而已。除此之外,財富幫Debug頁面還設置了切換App運行環(huán)境的功能,把這個功能放到Debug頁面是因為這是一個敏感操作,一般用戶不應該擁有這個權限,甚至不應該知道這個功能。這個功能主要是為了方便開發(fā)人員和測試人員用一個安裝包去切換環(huán)境以測試App在不同環(huán)境下的表現,免去了開發(fā)人員針對不同的環(huán)境要打不同安裝包的瑣碎工作。
客戶端多環(huán)境切換
在實現這個功能之前,我們首先要思考一個問題,測試環(huán)境、正式環(huán)境以及開發(fā)環(huán)境和預發(fā)布環(huán)境等真正的區(qū)別在哪里?仔細想想后不難發(fā)現,UI交互、業(yè)務流程等幾乎是一模一樣的,唯一不同的就是請求接口的Url,和某些第三方的App key,App id等,比如說推送的App Key,微信分享的App id之類的。
為了實現環(huán)境切換功能,我們首先要實現一個管理請求Url的類,我們可以暫時把這個類叫做CFBRequestUrlManager,它主要負責根據不同的環(huán)境返回不同的請求url。然而,我們到底該如何標記環(huán)境呢?很簡單,客戶端本地存儲一個變量app_env就可以?,F在數據層就基本ok了,我們還需要在Debug頁面加上一個分段控件用來讓用戶操作,記得在分段控件切換環(huán)境時更新下app_env就可以?,F在關鍵的問題來了,切換環(huán)境后除了更新app_env,我們還需要做其它事情么?當然需要了,想想推送,推送環(huán)境的初始化注冊等操作都是在App啟動時做的,再想想App里某些模塊的緩存,如果不清除掉的話,我們切換到了新環(huán)境卻還在用著上一個環(huán)境的緩存,這會引起多大的bug哇;這里只是舉個例子,真實情況下應該還有很多具體的問題。簡言之,我們需要在App切換環(huán)境之后做好清除緩存等工作。最后也是最重要的,為了讓推送等需要在App啟動時才能執(zhí)行的邏輯實時觸發(fā),我們應該退出App。
推送debug
1.推送日志的建立
推送的使用場景往往是在App發(fā)布之后,這個時候我們的App需要根據服務器推送過來的信息來決定App展示什么樣的頁面,執(zhí)行什么樣的邏輯;此時,我們是無法用IDE來Debug的。倘若能針對具體的業(yè)務邏輯建立一套自己的推送日志,那么我們調試推送功能時將事半功倍。財富幫目前的推送有好幾類,以資訊推送來做個簡單例子,對于資訊推送我們很關心推送過來的點擊url,以及是否允許分享,分享url等,我們把這些信息都寫入日志的話,假如某條資訊推送過來出現了打開為空白頁面,或者不允許的分享的卻顯示了分享按鈕等bug時,我們就能很容易地定位到錯誤,然后迎刃而解之。
2.別名賬號的建立
有的推送功能提供商在測試單推功能時是不允許使用deviceToken的,它們需要一個設備別名,財富幫現在所使用的信鴿推送就是這樣。為了測試單推功能,我們在Debug頁面設定了一個綁定推送別名的功能以方便測試單推功能,必須要提醒的是,設備別名的綁定時機是在App 啟動的時候,所以當我們綁定了新的設備別名之后,必須先重啟App才可以重新測試。
托管式網絡請求類
在移動客戶端的開發(fā)過程中,我們需要經常處理網絡請求,關于一個網絡請求我們大概有三個關注的時間點,請求開始,請求成功或失敗。對于大部分請求,我們都需要做同一件事情,請求開始時顯示loading動畫,成功或失敗后移除loading動畫,失敗后根據失敗原因顯示不同的UI,如果是因為超時原因,頁面應該提供一個非常重要的刷新按鈕,點擊之后能重新請求數據;如果是網絡情況不好或服務器內部錯誤,則應該根據錯誤原因顯示相應的提示頁面,此時不需要提供刷新按鈕。
由于在一個App內,loading視圖,網絡超時視圖,以及服務器錯誤視圖基本上都是統(tǒng)一風格的,所以對于這三個視圖的具體表現,我們完全可以提供抽象接口去實現。我們可以根據一個網絡請求對象是否實現了相關接口來決定這個網絡請求對象是否需要托管,如果實現了則為托管狀態(tài),執(zhí)行相應的托管邏輯,也就是請求開始顯示loading視圖,請求失敗顯示相應的錯誤提示頁面。這種情況一般適合于一個頁面的主網絡請求,所謂主網絡請求就是請求下來的數據能夠渲染這個頁面的大部分區(qū)塊的UI。對于一些小的附帶請求,只影響局部UI的請求,我們不應該實現托管,以免影響頁面整體的視覺表現。這樣我們就初步實現了托管式網絡請求類,但是如果每個請求我們都需要實現一次接口那不是很累么?!
所以剛才設計的網絡請求類應該只能是一個基類。一般情況下,一個App里的網絡請求loading圖,網絡請求超時圖應該是相同的,為了貫徹DRY原則,我們還需要設計一個子類繼承剛才的基類,這個子類應該實現相應的loading視圖,網絡超時視圖邏輯接口。最后,為了讓基類更健壯靈活,我們還需要提供一個BOOL標記來決定是否啟用托管,如果啟用,則執(zhí)行l(wèi)oading,網絡視圖等邏輯,反之,則不執(zhí)行。