RxJava+Realm+MVP+ARouter+Retrofit框架搭建

去年就一直想搭建一個框架边器,可惜一直拖到年初才有時間撼短。熟話說基礎不牢地洞山搖靶擦。當然我們要先看項目的組織結構腮考,既然是一個通用的庫,就只能包括通用的模塊玄捕。
項目模塊劃分
|- base
|-BaseApplication
|-BaseActivity
|-BaseFragment
|-BaseActivityLifeCircleCallbak
|-db
|-message
|-network
|-okhttp
|-retrofit
|-HttpManager
|-utils
|-ARouter
|-monitor
這里我們對于模塊的組合采用了Router方式踩蔚,對于ios或者前端的人士應該比較熟悉,對模塊復用解耦比較簡單枚粘,大體項目結構如上馅闽,有些小的類就沒寫了,以及一些模塊持續(xù)更新中馍迄。下面的講解就以我的添加順序來了

Network

網絡模塊在一個App中屬于大模塊福也,而且相對獨立,所以我選擇首先建立攀圈。這里選取了Retrofit+Okhttp3的插件暴凑,本身都是square出品的Retrofit與其說是為了OkHttp而生的也不過分,關于OkHttp的分析請參考我的另一篇OkHttp核心理解,關于Retrofit是基于主流請求都是restful風格赘来,使用請參考Retrofit使用沒什么大的東西搬设,主要是對一些注解的理解。
這里可操作性比較大的就在與我們的OkHttp里面撕捍,他的精髓大概就是Interceptor了吧拿穴。
因為網絡模塊可以分為日志,緩存忧风,Https默色,授權(廢棄)。

  1. 日志模塊我們往OkHttpClient里加了一個ApplicationInterceptor狮腿,獲取request以及Response的信息腿宰,這里日志我用了自己上傳Jcenter的項目,比Logger難看點,附上github地址BullDog
  2. 緩存這邊情況比較復雜缘厢,大概講下遇到的困難吃度,后來就放棄了第一種方案,本來如果設計合理的話贴硫,我們其實可以使用Interceptor直接實現(xiàn)無網絡使用緩存椿每,有網絡更新的策略伊者。但是由于OkHttp的默認緩存是只支持Get的與我們的實際情況有所出入,反正我也講下合理情況下的方案间护。
  • 首先我們需要了解下DiskLruCache,這個本來是一個開源項目亦渗,使用文件緩存,被google官方推薦汁尺,也被OkHttp內置了法精,區(qū)別就是OkHttp是用了Okio的流處理(Sink,SourceOkio使用痴突,基本操作不難)搂蜓,需要了解DiskLruCache的請自行Google,由于本身的Api不太友好我進行了二次封裝DiskLruCacheHelper

  • 先講下設計合理的處理辽装,本身我們的請求可以帶Cache-Control這個頭帮碰,在無網條件下只要我們在request內加入CacheControl.FORCE_CACHE這個參數(shù),OkHttp內部會自行查詢有無該緩存進行返回

  • 為什么說Get才需要緩存呢如迟,其實我們緩存需要一個Key,如果是get的話我們直接可以把url作為key攻走,但是如果是post其實我們區(qū)分key的是post body里面的信息殷勘,這樣就比較難處理,比如一個人的信息昔搂,get的話是帶uid這類標識符的玲销,post的話我們就無法區(qū)分是哪個人的信息了。然后是解決方法摘符,我這邊的網絡請求是加了一層殼的贤斜,我們知道Retrofit結合Okhttp返回的結果是Observable,所以我們在Subscriber里面做文章逛裤,在返回接過錢我們既可以捕捉異常瘩绒,又可以加緩存,這邊的請求我多了一個cacheKey的參數(shù)带族,可以自由配置我們需要緩存的信息锁荔。根據(jù)我們的策略我們先判斷有無網,有網則更新緩存蝙砌,無網則取出緩存返回阳堕。

  1. Retrofit模塊,這個模塊沒什么好講择克,主要是用于寫請求的恬总,以及一些基本配置
  2. 最后加了個BaseNetWorkCallbackBean用來規(guī)范我們的網絡返回

總結,這邊模塊分的比較多肚邢,主要遵循組合大于繼承壹堰,有利于以后的拆解閱讀。

DB

Db模塊以前我們用的大多是core data比如說greenDao,我用的這個realm在ios平臺用的比較多缀旁,網上有關于這塊區(qū)別的講解记劈,主要還是從效率上來講,realm明顯要高出core data這塊很多并巍,有點缺陷就是對bean的污染目木,每個bean都要繼承RealmObject,照某網友的說法就是強奸代碼懊渡。Realm官方網站刽射。
我這邊主要是對Realm進行了簡單的封裝,對一些常用操作簡單化剃执,比方說insert誓禁,query,delete由于Realm不支持sql語句查詢肾档,所以自由度相對也就差點摹恰,不過移動端不像后端需要復雜查詢各種外鍵條件的,我封裝的幾個查詢應該已經滿足日常使用了怒见,此外Realm還支持異步俗慈,但有一點千萬要注意,Realm的操作類并非單例遣耍,你獲取一個闺阱,他就線索樹里面多一個引用,所以每次使用完記得釋放舵变,這里我是在BaseActivity的生命周期內控制的酣溃,只不過異步的情況要復雜一點,在api封裝上也是講realm對象作為參數(shù)傳入纪隙,在最后進行釋放赊豌。

Base

這個是比較基礎的部分,為什么不選擇先建是因為有些東西是隨著模塊的加入逐步完善的绵咱,比方說前面提到的Realm亿絮,還有后面的RxBus。

  1. BaseApplication麸拄,這個類的核心在于一些插件的初始化派昧。涉及到這個如果我們的插件比較多,勢必影響到APP的啟動速度拢切,所以我們最簡單的處理就是啟用線程池蒂萎,引入異步初始化,但是需要注意有些操作是一開始就需要的只能放在同步操作里淮椰,比方說Log框架的加載五慈。這里我封裝了一個ApplicationInitializer纳寂,主要的就是使用cacheThreadPool來控制初始化,分離的目的也是為了單一職責泻拦。以下為一些類的初始化
        BLog.init();
        /* 其他初始化任務無時序要求可多線程處理 */
        cachedThreadScheduler.execute(new Runnable() {
            @Override
            public void run() {
                Realm.init(application);
                RealmConfiguration realmConfiguration = new RealmConfiguration.Builder()
                        .name(DB_NAME)
                        .deleteRealmIfMigrationNeeded()
                        .build();
                Realm.setDefaultConfiguration(realmConfiguration);
            }
        });

        cachedThreadScheduler.execute(new Runnable() {
            @Override
            public void run() {
                Fresco.initialize(application);
            }
        });
        cachedThreadScheduler.execute(new Runnable() {
            @Override
            public void run() {
//                LeakCanary.install(application);
            }
        });
        cachedThreadScheduler.execute(new Runnable() {
            @Override
            public void run() {
//                BlockCanary.install(application,new AppBlockCanaryContext()).start();
            }
        });
        cachedThreadScheduler.execute(new Runnable() {
            @Override
            public void run() {
                ARouter.init(application);
            }
        });

除了初始化這塊毙芜,ICE_CREAM_SANDWICH以后我們可以通過在Application內注冊ActivityLifeCircleCallbak監(jiān)聽activity的生命周期,后面可以了解到Arouter也可以檢測到争拐,或者第三種方案就是在Application內維持一個List<Activity> activities腋粥,BaseActivity生命周期內去更新這個變量。

  1. BaseActivity 這個作為跨頁面控制比較重要的結構架曹,可以封裝一些比較常用的方法隘冲,這里我主要維護了一個List<Fragment> fragments,用來管理activity下面的fragment绑雄,因為當前app主流還是單activity多fragment的模式展辞,還有就是保存一些經常使用的變量,比如Realm万牺,Rxbus還有ioc框架的初始化罗珍,這里的ioc我也是自己寫的 比較簡單,只有click脚粟,longclick兩個事件Potato
Utils

這個模塊就大概講解下覆旱,主要都是一些基本的工具包,各個項目通用珊楼,github有提供下載通殃。

Rxbus

類似與EventBus度液,因為本身我們引入了RxJava厕宗,所以用rxjava來實現(xiàn)事件總線是更可取的方法。參考rxbus實現(xiàn)堕担,在post中采用了tag已慢,更符合eventbus的使用習慣,具體就是封裝Event包裹了一個tag對用戶透明霹购,在返回的時候先filter篩選然后采用flatMap進行轉化

MVP

關于mvp模式的實現(xiàn)佑惠,中間想了蠻久,主要是糾結于怎樣使用范型齐疙,在BaseActivity進行P跟V的綁定膜楷,以及P跟M的關聯(lián),參照了google的mvp實現(xiàn)贞奋,使用了contracts使接口或者抽象類更加關系明確赌厅,集中。
這里我們實現(xiàn)了BasePresenter<T>這里的T是用來引入M的轿塔,而V的引入在BaseActivity<V extends BasePresenter>這樣就形成了一個V初試化P特愿,然后P初始化M的鏈仲墨,P就成為了關鍵,當V destroy的時候就P就解綁V揍障,釋放M目养,把業(yè)務邏輯放到P上,插句題外話毒嫡,中間了解了下mvvm也就是m-vm-v的模式癌蚁,直接在布局層就將數(shù)據(jù)跟v通過viewmodel緊密結合了,省掉了findViewById的工作审胚,但個人不太喜歡這種模式匈勋,感覺可讀性較差,分層不是那么明確

monitor

監(jiān)視框架膳叨,已經引入了blockcanary洽洁,leakcanary,接下來要引入aop設計進行關鍵點檢測菲嘴,然后接入友萌饿自,這個就是中國版的firebase當初去外企面試被問倒了,哈哈哈

test

測試框架還沒開始龄坪,主要分單元測試昭雌,espresso ui測試,mock數(shù)據(jù)...測試框架蠻多的健田,最近再看烛卧,按順序來吧

ARouter

路由機制,github上有兩個下載量多的妓局,之所一選擇ali的完全是信仰吧总放,基本就是一些配置,使用說明官網有ARouter好爬,采用這種機制也是偶然在android weekly上看到人家一個老司機用這種框架搭建中小型項目局雄,也算是一種新的嘗試吧。

2017/3/1:更新Mvp

文章未完待續(xù)存炮,盡量月底前完成接下來的工程炬搭,歡迎喜歡這文章的朋友下載我的代碼,幫我發(fā)現(xiàn)問題穆桂,完善框架SpaghettiFrame

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末宫盔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子享完,更是在濱河造成了極大的恐慌灼芭,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驼侠,死亡現(xiàn)場離奇詭異姿鸿,居然都是意外死亡谆吴,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門苛预,熙熙樓的掌柜王于貴愁眉苦臉地迎上來句狼,“玉大人,你說我怎么就攤上這事热某∧骞剑” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵昔馋,是天一觀的道長筹吐。 經常有香客問我,道長秘遏,這世上最難降的妖魔是什么丘薛? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮邦危,結果婚禮上洋侨,老公的妹妹穿的比我還像新娘。我一直安慰自己倦蚪,他們只是感情好希坚,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著陵且,像睡著了一般裁僧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上慕购,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天聊疲,我揣著相機與錄音,去河邊找鬼脓钾。 笑死售睹,一個胖子當著我的面吹牛桩警,可吹牛的內容都是我干的可训。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼捶枢,長吁一口氣:“原來是場噩夢啊……” “哼握截!你這毒婦竟也來了?” 一聲冷哼從身側響起烂叔,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤谨胞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蒜鸡,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胯努,經...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡牢裳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了叶沛。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蒲讯。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖灰署,靈堂內的尸體忽然破棺而出判帮,到底是詐尸還是另有隱情,我是刑警寧澤溉箕,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布晦墙,位于F島的核電站,受9級特大地震影響肴茄,放射性物質發(fā)生泄漏晌畅。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一寡痰、第九天 我趴在偏房一處隱蔽的房頂上張望踩麦。 院中可真熱鬧,春花似錦氓癌、人聲如沸谓谦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽反粥。三九已至,卻和暖如春疲迂,著一層夾襖步出監(jiān)牢的瞬間才顿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工尤蒿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留郑气,地道東北人。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓腰池,卻偏偏與公主長得像尾组,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子示弓,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內容