在以往的開發中,咱們一般會使用MVC的模式進行開發,這樣致使了Activity處理的邏輯很是的複雜,並且耦合度很是高,代碼結構混亂、層次不清,各業務技術方案不統一,冗餘代碼充斥項目的各個角落;甚至連基本的包結構也是胡亂不堪,項目架構更是無從談起。你們只不過是不停地往上堆砌代碼添加新功能罷了。前端
其中業務層是一種非標準的 MVC 架構,Activity 和 Fragment 承擔了 View 和 Controller 的職責:android
爲了適應項目快速開發以及項目中代碼的複用,解決項目中的耦合度。咱們不斷引入了 Retrofit、UniversalImageLoader、OkHttp、ButterKnife 等一系列成熟的開源庫,同時咱們也開發了本身的 UI 組件庫 UIComponent、基礎工具庫 CommonUtils、基於第三方地圖封裝的 MapSDK、即時聊天模塊 ChatLibrary 等等。這樣就由基礎組件層、業務組件層和業務層組成的三層架構。以下圖:git
前面這種分層的架構自己是沒太大問題的,即便到了如今咱們的業務項目也已然是基於這種分層的架構來構建的,只不過在不斷的迭代中咱們作了些許調整(分層架構後面在介紹組件化和模塊化的時候會詳細介紹)。可是隨着業務的不斷迭代,咱們慢慢發現業務層這種非標準的 MVC 架構帶來了種種影響團隊開發效率的問題:github
Activity 和 Fragment 愈來愈多的同時承擔了 Controller 和 View 的職責,致使他們變得及其臃腫且難以維護;算法
因爲 Controller 和 View 的揉合,致使單元測試起來很困難;數據庫
回調嵌套太多,面對負責業務時的代碼邏輯不清晰,難以理解且不利於後期維護;緩存
各層次模塊之間職責不清晰等等安全
總體項目架構以下圖:微信
View Layer: 只負責 UI 的繪製呈現,包含 Fragment 和一些自定義的 UI 組件,View 層須要實現 ViewInterface 接口。Activity 在項目中再也不負責 View 的職責,僅僅是一個全局的控制者,負責建立 View 和 Presenter 的實例;markdown
Model Layer: 負責檢索、存儲、操做數據,包括來自網絡、數據庫、磁盤文件和 SharedPreferences 的數據;
Presenter Layer: 做爲 View Layer 和 Module Layer 的之間的紐帶,它從 Model 層中獲取數據,而後調用 View 的接口去控制 View;
Contract: 咱們參照 Google 的 Demo 加入契約類 Contract 來統一管理 View 和 Presenter 的接口,使得某一功能模塊的接口能更加直觀的呈現出來,這樣作是有利於後期維護的。
模塊層
業務邏輯層
基礎組件層
爲何要這麼分?首先從總體模式上看跟微盤的架構大同小異,不少模塊都是相同的,可能UI展示跟接口數據不大同樣,業務邏輯是差很少的,可是目前很難再從之前的微盤中直接重用。因此分紅單獨的模塊。
第一利於團隊多模塊開發,第二利於開發速度,只針對單個模塊進行編譯,編譯速度提高了。第三每一個模塊均可以單獨成爲APK運行,方便代碼調試。第四就是易用性和重用性高。
對整個APP進行功能拆分,單獨成立模塊,每個模塊都獨立依賴基礎組件和業務組件。咱們能夠把 Basic Component Layer 和 Business Component Layer 放在一塊兒看作是一層SDK,新的業務或者項目只須要依賴 SDK 就好。甚至咱們能夠作得更極致一些,開發一套本身的組件管理平臺,業務方能夠根據本身的需求選擇本身須要的組件,定製業務專屬的SDK。業務端和SDK 的關係以下圖所示:
封裝了與模塊層的數據交和UI回調,實際上就至關於Presenter的職責。調用接口以及數據處理都在這一層裏面作,最終把結果回調給界面。
另外的職責就是封裝經常使用的公共模塊如數據庫操做,緩存操做,HTTP請求等。
這一層可使用RxJava,能夠很好的解決嵌套回調的問題。RxJava系列的文章能夠參考這裏
各 Layer 間嚴禁反向依賴:每一個層要進行依賴,先畫好層於層直接的調用關係,禁止相互依賴。有相互依賴的把公共部分單獨拆分。
這一層比較好理解,封裝基礎組件,好比模塊化須要用到的Router來鏈接,而且能夠管理Activity的生命週期。還有一些基礎UIWidget庫,好比股票的圖表。
項目間的依賴經過私有maven庫進行管理,特別是sdk跟presenter這一層,強制把UI跟邏輯分離。使用maven的一個弊端就是須要頻繁的上傳跟從新build。前期能夠在項目用complie project(':sdk') 來依賴。
API接口做爲核心的一層,每一個模塊都須要調用該層,咱們採用分功能來設計接口,並提供統一的接口工廠來獲取接口的實例。UML圖以下:
接口層編碼的時候要注意:
全站使用HTTPS證書
如何避免回調Listener的內存泄漏?(緣由:回調都是經過onSuccess()方法去處理,很容易引用到Context,而致使Http線程沒辦法退出)
封裝成基礎類去發請求,能夠控制token失效從新發請求的過程。
採用Retrofit2 +okhttp3
接口緩存策略(參考Volley的緩存):
若是緩存中存在,先從緩存讀取。
每個請求都有緩存時間,緩存過時或者失效後從新獲取。
能夠配置每一個請求啓用或者禁用緩存,好比一些增刪改查操做就不須要用到緩存。列表的形式通常要緩存。
緩存默認是關閉的,根據須要來給請求緩存。
通常狀況下咱們的實體層(entity、bean、model)這些都是跟sdk處於一層的,爲了不每一個模塊爲了使用實體層而引用sdk,因此要把這個實體層單獨一層出來,避免相互之間有反向依賴的可能性。
除了經常使用的實體層以外,Model層還具備負責檢索、存儲、操做數據,包括來自網絡、數據庫、磁盤文件和 SharedPreferences 的數據的功能,只是都歸根到Model這一塊來。實際上他們都是單獨開來的。
View劃分紅若干小模塊,不僅僅可使用當前項目,更爲了之後方便集成到其餘項目當中去。
組件化和模塊化使得程序更加靈活,爲了不在app對各個模塊以及組件的依賴當組件發生改變的時候代碼修改很大。因此由RouterManger去統一管理各個模塊組件之間的跳轉。
實現方式能夠採用ARouter,支持Url方式的跳轉。
接口使用HTTPS加密證書進行傳輸,並進行用戶鑑權,用戶鑑權方面則打算採用Token方式。用戶登陸以後分配一個accessToken和一個refreshToken,accessToken用於發起用戶請求,refreshToken用於更新accessToken。accessToken會設置有效期,能夠設爲24小時。而用戶退出登陸以後,accessToken和refreshToken都將做廢。從新登陸以後會分配新的accessToken和refreshToken。
而後,我還打算在App層級分配AppKey和AppSecret,Android和iOS分別分配一對。每次向服務端發送請求時,AppKey都必須帶上,服務端會對相應的AppKey進行校驗。而AppSecret則須要安全保存在客戶端,也不能在網絡上進行傳輸,防止泄露。AppSecret只用於加密一些安全性級別較高的數據,以及爲URL生成簽名。URL簽名算法步驟以下:
將全部參數按參數名進行升序排序;
將排序後的參數名和值拼接成字符串stringParams,格式:key1value1key2value2...;
在上一步的字符串前面拼接上請求URI的Endpoint,字符串後面拼接上AppSecret,即:stringURI + stringParams + AppSecret;
使用AppSecret爲密鑰,對上一步的結果字符串使用HMAC算法計算MAC值,這個MAC值就是簽名。
鑑權流程以下:
最後總結設計爲:
接口採用HTTPS和簽名證書進行傳輸
接口參數經過排序 & URL & AppSecret 最終經過HMAC加密生成sign參數
利用底層JNI的so庫提供接口進行加密,保證密鑰的安全性
敏感字段so加密傳輸,好比設計密碼、銀行卡號、身份證號碼等有關用戶安全信息的字段
數據安全利用底層JNI實現,打包成so庫提供JAVA接口調用。把公鑰信息、加密算法放到so庫裏面防止反編譯信息泄漏。
APK安全
android的apk文件其實是壓縮文件,很容易被反編譯工具進行反編譯,像微信這些apk都能被反編譯。爲了增強APK的安全性,設計以下:
發佈時對代碼進行混淆編譯
第三方APK文件加固
第三方加固網站:
行情模塊(Quotation Module)
行情使用WSS安全傳輸。
行情之後臺服務的形式,在Application onCreate() 的時候就開始創建WebSocket鏈接。沒有訂閱行情的時候關閉行情鏈接,當訂閱的時候再次開啓行情鏈接。目的爲了節省流量以及手機電量。
由於行情基本上每一個頁面都會用到,因此採用發佈訂閱的觀察者模式進行設計,實現原理:
每一個Presenter均可以註冊本身須要的行情(Quotation Filter),當WebSocket 接收到對應的Quotation Filter的時候調用EventBus中間件發送消息。最終會回調到該類的定義的事件方法中去。
把數據處理好前端須要展現的數據實體返回。如行情的狀態是上漲仍是下跌的狀態。
統一使用QuotationManager來管理行情的鏈接、訂閱;抽象成QuotationAction 來管理註冊不一樣的行消息,解析返回。
行情服務接口方法:
start() 啓動服務
stop() 中止服務
getStatus() 獲取當前狀態
register(object handler, QuotationAction action) 訂閱行情
unregister(); 反註冊行情
依賴項:API
說明:
User Manager :用戶管理,管理當前用戶的登陸狀態、用戶信息、用戶操做(退出登陸,狀態維持,Token刷新)
User Module:用戶模塊,跟用戶相關的各個功能的業務處理、數據處理
依賴項:API、行情模塊
其餘模塊須要調用交易模塊都是經過路由跳轉的方式調用不會直接調用到內部方法裏面,因此交易模塊重點仍是調用API進行數據處理:
本文參考連接: