1. Android開發框架的選擇
我們知道原生Android開發已經是一個基礎的MVC框架,其中xml部分被認為是View層,Activity層是Control層,所以在項目剛開始開發的時候并沒有遇到太多問題。
但是在實際項目中,Activiy層除了做C層的工作以外,還會有承擔部分View層的工作,這樣導致了很容易出現一個Activity的超級類,維護起來十分復雜。目前我們自己的項目比這個情況更糟糕,Activity一個類直接寫了所有的業務邏輯,導致這個類錯綜復雜,沒有任何層級劃分,代碼閱讀和修改都十分的困難。
需要解決這些問題,需要做2個維度的解耦工作
1.分層
2.模塊化
兩種的方式最終目的是一樣的,只不過一個是縱向層面上的解耦,一種是橫向層面上的解耦。
目前android主流架構中MVC已經不太適用了,比較流行的是MVP和MVVM,但是MVVM需要用到谷歌的databinding,而目前這部分技術不太成熟,有許多問題。而MVP的架構已經足以滿足我們的需求和后續擴展了,所以選用MVP架構。
2.分層架構MVP和模塊化的實現
MVP實際上是在MVC的基礎上實現的,在android端具體思路就是將activity層作為一個view層剝離出來,Presenter層作為中間層,主要做的是一些邏輯上的處理和消息的傳遞,Model用來存儲數據。
這是一個比較典型的MVP架構的結構圖,用戶事件由View層響應,然后通過presenter進行消息傳遞,最后從model層獲取數據,再從presenter層返回給view層做數據刷新。
具體如何實現呢,下面將用代碼直接說明:
通過包結構,我們可以看一個MVP結構的大致劃分,主要有接口有。
View層接口:ICreditView
主要是一些進行UI刷新和狀態的處理。
View層的具體實現
Activity里面包含了2個類,一個是View層的對外接口ICreditView,一個是P層的CreditPresenter。
從上面的所有代碼可以看到,View層將自己的接口ICreditView交給了Presenter, 而Presenter層持有Model層的也只是一個接口。通過Presenter層將業務層與展現層隔離了開來,這樣的好處是什么?
我們知道接口的一個作用通常是用來抽象行為,對外部屏蔽實現細節。所以對于View層來說,業務細節被屏蔽了,對業務層來說,展示細節被屏蔽了。而對于處于中間的Presenter層來說,它就像一個接口拼裝器,把View層發出的請求傳遞給業務層,把業務層返回的數據又送還給View層展示,至于前后兩端怎么實現的,它才不用關心。
接口的第二個作用是可以用來切換實現。我們先看下面的代碼。
Model層接口:ICreditDataSource
主要是一些數據存儲和數據提取的處理。
我們可以通過實現這個類來實現一些我們需要的model數據
這里的數據都是本地的,獲取和存儲都沒有任何問題,但是在我們實際工作中,很多數據是從我們的服務端獲取的,這在做需求的時候就會有個問題。服務端的同學還沒來得及做好相關的接口,我們可以直接自己定義一個Test的Model實現類,這樣就可以先做好邏輯和界面,等服務端做好后,再直接進行聯調,就OK了。
類似的應用場景其實有非常非常多,這里我們就看到了使用接口解耦的一個好處了,不僅把業務層和展示層解耦開來,還把Android開發同其它的一切的外部數據依賴都解耦開來。
到現在為止一個基于MVP簡單框架就搭建完成了,但其實還遺留了一個比較大的問題。
我們從Model層獲取數據,大部分都會是一個耗時操作,而android又規定主線程不能做耗時操作和網絡請求,否則會出現ANR甚至直接報錯。
正常情況下,我們想要做耗時操作,都會啟動一個線程,然后完成后做一次線程切換,回到主線程做處理,按照android給我們的一些方式,可以用Handler,用可以用runOnUiThread,例如這樣:
這里其實看起來還算OK,但是存在2個隱患。
1、多次調用這個方法,會多次啟動線程,造成不必要的資源浪費
2、如果線程多次切換,這樣寫就會有非常多的嵌套,十分影響代碼體驗。
好在有了RxJava ,可以比較方便的解決這個問題。
3. 使用RxJava來進行線程控制
RxJava是一個天生的做異步的工具,他的詳細介紹可以去看扔物線大神的這篇介紹,寫的非常詳細,很適合初次學習RxJava的同學去看。
http://gank.io/post/560e15be2dca930e00da1083
還是回到剛才的那段線程切換的代碼,如果我們需要用RxJava做要怎么做呢?
簡單解釋下,mDataSource就是我們的Model層,Schedulers.io是RxJava提供的IO管理線程,這樣就解決了我們之前的第一個問題,線程被反復調起浪費資源的問題。同時AndroidSchedulers.mainThread是android線程,我們可以反復在他們之間切換,這樣按照RxJava的書寫規范,完全就可以避免多層嵌套的問題。
當然RxJava的使用場景遠遠不止這些。下面列出了一些常見的RxJava的常用場景,其實還有更多的其它功能等待著大家去挖掘。
1、取數據先檢查緩存的場景
2、需要等到多個接口并發取完數據,再更新
3、一個接口的請求依賴另一個API請求返回的數據
4、界面按鈕需要防止連續點擊的情況
5、響應式的界面
6、復雜的數據變換
4、Retrofit的使用
Retrofit是一個基于okHttp的網絡框架,他的優點在于基于注解的接口式編程,不用寫具體的實現,這樣更進一步的解耦了Presenter層和Model層。但是需要使用到這個框架,有一些前提條件,就是服務端必需支持REST風格。我們自己的服務端接口目前并沒有對這方面進行支持,但是調用第三方的接口中,Face++對REST進行了支持,而且老的接口使用的是asyn-http,這個是一個基于httpClient的框架,谷歌在6.0以后放棄了對這部分的支持,所以這次重構也對這部分代碼做了一次重構。
具體的retrofit的使用可以網上搜到,有很多相關的教程,這次算是一次項目中的實踐,可惜的是我們的服務端目前沒有時間做出對REST的支持,后續如果支持到,會更多的研究里面很多的細節性問題了。