淺談安卓項目框架發展
來自: http://blog.csdn.net//guijiaoba/article/details/50223227
淺談安卓項目框架發展
翻譯自Android Application Architecture
Android開發的生態環境變化非常快,每時每刻都會有一些新的庫和工具產生。
2012年前
2012年的時候,當時安卓程序的主要框架是,沒有什么網絡請求庫。任何耗時操作都是使用AsyncTasks完成。基本框架圖如下所示。
代碼中只有2層:數據層、UI層。
- 數據層:使用REST API來請求數據,保存數據,為界面提供數據的支持。
- UI層:顯示數據層的數據,同時處理用戶的事件。
同時會APIProvider來提供一些接口方法,給Activity或Fragment來調用請求數據,APIProvider內部使用URLConnection結合AsyncTasks的方式,來請求數據。當數據回來后,通過一些列的回調給Activity和Fragment。
CacheProvider用來保存一些緩存數據,如SharedPreferences來保存簡單數據,用SQLite來保存復雜的數據,當然CacheProvider也會提供一些回調給UI層。
問題
通過以上的方法來架構程序,會使的UI層很重。比如,程序中有個功能是用ListView來加載圖片的場景,同時用sqlite緩存的技術。那么正常情況下,Activity需要做如下的操作。
- 調用APIProvider中loadPosts(callback) 的方法。
- 在回調中等待獲取數據成功,然后再調用CacheProvider的savePosts(callback)方法來緩存數據。
- 等待數據保存成功后,然后再把數據顯示在ListView中。
- 假如某一步失敗了,那么還要在某個回調中單獨處理。
這是一個比較簡單的例子。在實際的情況下,REST API可能會返回一個復雜的數據,Activity可能需要對數據做一些處理,才能顯示。比如其他一些使用場景,要從Play Server SDK中異步加載郵件名稱,那么在代碼中可能會有回調方法嵌套的問題。如果這種回調嵌套太多,那么對于程序來說,簡直是一團糟,一個大坑。
總結
- Activity和Fragment會變得非常龐大,并且難以維護。
- 太多的回調嵌套,不方便未來代碼的擴展。
- 不能進行單元測試,有很多的邏輯代碼放在UI層,就非常難以測試。
使用RxJava架構
上面的說的程序框架我們使用2年多,當然我們也做了一些修改。比如,我們在APIProvider中使用Volley
來進行網絡請求。然后我們的代碼就變得非常難以測試,掉進一個回調嵌套的大坑里面。
2014年的時候,我們開始了解到RxJava
,自己也經常寫一些小的Demo,發現它可以解決回調嵌套問題。如果你還不了解RxJava,你可以在這里了解到。簡單來說,Rxjava可以讓你的異步方法變成流一樣處理,同時你還可以對流中數據的進行轉化、過濾、組合等。
使用Rxjava后,我們的項目結構變成如下所示。
相對于來第一個版本的架構來說,我們對數據層和UI層進行了分離。數據層變成了一個數據管理類(DatManager),數據管理類會持有很多數據幫助類(Helper classes)。UI層就是使用安卓系統提供的組件來顯示數據,如Fragment,Activity,ViewGroup等。
數據幫助類(Helper classes)通常是一些第三方的框架和庫,用來保存和處理數據,很方便。比如通過REST API接口來獲取數據,就可以使用第三方的工具。不同的程序獲取數據方式是不同的,但是相同點是:
- PreferencesHelper可以保存和讀取SharedPreferences中的數據。
- DatabaseHelper可以訪問數據庫
- Retrofit Services可以訪問web服務器中的數據,我們把Volley替換成Retrofit,因為Retrofit提供RxJava方式的調用接口。
項目中大部分的public方法都變成了RxJava Observables的方式。
DataManager就是整個項目的大腦,它使用Rxjava的方式,從各種幫助類中獲取數據,然后對數據進行處理,最后把數據傳給界面層,界面層不再需要關心怎么處理數據了,直接用來顯示。
比如我們需要一個顯示博客內容,整個一個流程如下所:
- 通過REST API來獲取一個博客的列表。
- 使用DatabaseHelper來保存獲取到的數據。
- 當我們需要現在在界面中過濾顯示今日所寫的博客時候,就可以使用Rxjava對數據進行過濾。
UI層中組建只需要調用簡單調用某個方法,然后會使用Rxjava中Observable來接受數據。或者可以通過適配器模式,來顯示在不同的組建中。
最后我們在項目中使用了EventBus。EventBus就像安卓系統的中廣播一樣,可以隨時在數據層發送一個事件,然后界面中的可以有多個組建來接受這個事件。比如我有個退出登錄操作,數據層在調用signOUt方法后,發送一個退出登錄的事件。那么各種Activity都會受到這個事件,然后對界面上顯示的數據進行刷新。
新架構的優點
- RxJava提供統一的Observables和操作,這樣可以去除回調嵌套
- DataManager持有多個業務數據的倉庫,這樣Activity和Fragment只需要負責顯示,無需做過多的數據操作。
- 把數據從UI層移動到DataManager中,這樣很方便進行單元測試。
- 職責分明,DataManager只需要關注數據的存儲和處理,同時使程序變得容易測試。各種幫助類,也很方便的mock數據。
新架構的缺點
- DataManager將變的非常的大,非常難以維護。
- 雖然UI層變得非常簡單,只需要負責顯示數據。但是它還需要在Rxjava的回調中處理一些其他的業務邏輯。
MVP架構
又過一年左右,有一些新的架構方式出現。比如MVP和MVVM已經在社區變的流行起來。通過幾個Demo和文章,我們發現MVP可以對我們現在的架構做出優化。因為當前的架構的只有2層,添加一個MVP很方便自然。添加了MVP后,我們的架構變成了這樣。
現在的數據層已經變成了Model,更加清楚明了。
Presenters是把原先在Datamanager中加載數據的方法移動到Presenters中,當界面需要加載數據時候,只需要調用Presenters即可。當然也是采用Rxjava的方式。同時Presenters可以對加載數據錯誤,進行適當的處理,這樣比把所有的數據處理放在DataMangager中要好。
最后發現Presenters中的public方法跟都是使用Rxjava中的調用方式,然后Rxjava在調用DataManager中方法。
MVPView是一個顯示接口,用來顯示Presenters返回的數據,通常都是Activity、Fragment、ViewGroup來實現這個接口,然后再去顯示數據。
相對于第二個版本,我們發現UI層通含就是安卓系統提供的組件,如ViewGroup、Activity、Fragment。主要的不同的是,對不同Observables做不同的處理。
所以可以提供一個通用的數據展示方法,比如showError()
or showProgressIndicator()
。同時界面組件只需要處理一些事件就可以了,比如按鈕的點擊事件,然后加載數據,顯示數據。
MVP資料
優點
- Activity和Fragment變得更加輕量級,只需要處理用戶的響應,加載數據,顯示數據即可。
- 我們可以很方便的對Presenters進行修改,同時也可以mock些測試數據,這樣頁面測試也變的很方便。
- 假如Data Manager變的很大,可以把部分代碼移動到Presenters中。
問題
- DataManager是一個單例,并且這個單利非常大也很復雜。暫時還沒有很好的方法能夠解決。
很顯然,這不是一個完美的程序架構。實際上,并沒有一個好的架構能夠解決所有的問題。但是安卓的生態圈一直都在不斷的發展,同時我們自己也要不斷的探索,使我么你的程序更加健壯和優秀。
我希望你能喜歡這篇文章,同時也想這片文章對你有所益處。如問題,可以聯系我。
</div>