五五六六七七八八
?????????作為一名大三在讀的學(xué)生,想著自己的大學(xué)生活只剩下一年了敛苇,有了些許緊迫感,于是就打算找一份實(shí)習(xí)工作來(lái)增加自己的項(xiàng)目實(shí)戰(zhàn)經(jīng)驗(yàn)顺呕。 ??
????????想著互聯(lián)網(wǎng)公司都基本都有現(xiàn)成的項(xiàng)目枫攀,實(shí)習(xí)的話最多也就是對(duì)原有的代碼修改,增加功能株茶?所以最后進(jìn)了一家不大不小的外包公司来涨,想體驗(yàn)一下一個(gè)商業(yè)項(xiàng)目從落地到成型的過(guò)程。進(jìn)入公司以后启盛,被分配到一個(gè)給國(guó)外發(fā)包方做的項(xiàng)目(我只是個(gè)實(shí)習(xí)生萌新啊蹦掐,第一個(gè)項(xiàng)目就給外國(guó)人做,這樣好嗎喂)僵闯。
? ? ? ? 作為一個(gè)有過(guò)Android開(kāi)發(fā)經(jīng)驗(yàn)的菜鳥(niǎo)卧抗,也算在各個(gè)服務(wù)外包比賽中拿過(guò)些獎(jiǎng)的人(雖然大學(xué)的這種比賽很水,但是也是有些開(kāi)發(fā)的工作量的鳖粟,哈哈)社裆,我對(duì)一個(gè)項(xiàng)目的構(gòu)成,如何開(kāi)發(fā)等等向图,都有些了解泳秀。由于之前的比賽項(xiàng)目經(jīng)驗(yàn),都是我一個(gè)人獨(dú)立開(kāi)發(fā)Android端榄攀,所以對(duì)項(xiàng)目的架構(gòu)嗜傅、框架等都是怎么方便怎么來(lái),不怎么考慮代碼的可讀性檩赢,可復(fù)用性之類的東西(進(jìn)入公司實(shí)習(xí)之后才發(fā)現(xiàn)吕嘀,這些東西相當(dāng)重要啊)漠畜,之前為了方便币他,把業(yè)務(wù)邏輯,視圖綁定啥的都一股腦的放入activity類中憔狞,導(dǎo)致activity類過(guò)于臃腫蝴悉,給代碼的閱讀和修改都帶了極大的不便,但是由于自己的項(xiàng)目經(jīng)驗(yàn)缺乏瘾敢,從一開(kāi)始就給自己挖下的坑拍冠,之后不但很難填尿这,而且還越挖越深(單手捂眼笑哭.jpg),幸好只是我一個(gè)人自己開(kāi)發(fā)庆杜,不然要是協(xié)作開(kāi)發(fā)的話射众,估計(jì)會(huì)被小伙伴怒錘。
? ? ? ? 進(jìn)入公司以后晃财,從Android帶隊(duì)開(kāi)發(fā)大佬那邊拿到了項(xiàng)目的基礎(chǔ)開(kāi)發(fā)框架
????????品了一下叨橱,從我裸考過(guò)六級(jí)的水平來(lái)看,嗯断盛,這個(gè)presenter應(yīng)該是之前在書上看到過(guò)的MVP中的P沒(méi)差了罗洗。從網(wǎng)上找找資料學(xué)習(xí)學(xué)習(xí)。
ok钢猛,進(jìn)入正題伙菜。
????????MVP是Model、View命迈、Presenter的縮寫贩绕。Model表示模型,主要負(fù)責(zé)數(shù)據(jù)的加載壶愤;VIew表示視圖主要負(fù)責(zé)視圖綁定淑倾,界面的展示,界面邏輯跳轉(zhuǎn)等公你;Presenter是表示器踊淳,主要作為View和Model的中間人,完成他們之間的交互陕靠,從而實(shí)現(xiàn)高內(nèi)聚低耦合的思想迂尝。畫了一幅它們之間的關(guān)系圖。
可能這樣有點(diǎn)抽象剪芥,talk is cheap, show you the code.
? ? ? ? 先來(lái)看看我們項(xiàng)目組Android大佬的MVP框架實(shí)現(xiàn)垄开,
MainActivity.java:
MainContract.java:
MainPresenter.java:
????????大佬果然是大佬,已經(jīng)對(duì)各種基類進(jìn)行了封裝税肪,來(lái)方便我們這些萌新的開(kāi)發(fā)溉躲。(上面的代碼還用到了RxJava,emmmm其實(shí)這個(gè)對(duì)于我這個(gè)萌新來(lái)說(shuō)也是還沒(méi)有接觸過(guò)的技術(shù)益兄,之后也會(huì)更新RxJava相關(guān)的學(xué)習(xí)博客锻梳,要努力變強(qiáng)~)。
????????我們會(huì)發(fā)現(xiàn)净捅,其實(shí)上面這三個(gè).java已經(jīng)可以實(shí)現(xiàn)一個(gè)界面的完整邏輯疑枯,但是View有了,Presenter也有了蛔六,Model去哪了荆永?废亭??還有Contract又是什么鬼具钥?豆村??這還是MVP的設(shè)計(jì)模式嗎骂删?掌动??
????????一開(kāi)始桃漾,我也是懵的坏匪,又去大佬那邊學(xué)習(xí)了一波。了解到撬统,目前Android的MVP設(shè)計(jì)模式其實(shí)還沒(méi)有一個(gè)統(tǒng)一的標(biāo)準(zhǔn),基于MVP這個(gè)思想可以有很多的實(shí)現(xiàn)方式敦迄,上面展示的這個(gè)方式是Google官方提出的一種MVP實(shí)現(xiàn)方式恋追。
?????????谷歌官方的MVP實(shí)現(xiàn)方式中,弱化了Model的作用罚屋,將Model融入到了Presenter中苦囱,我們可以看到MainPresenter中的getBook方法,其實(shí)就是Model的實(shí)現(xiàn)脾猛。而Contract類撕彤,中文翻譯就是契約類,契約這個(gè)詞很形象猛拴,它作為view和presenter之間的接口羹铅,定義了view和presenter上所要實(shí)現(xiàn)的方法,然后view和presenter再各自實(shí)現(xiàn)其方法愉昆,讓整個(gè)界面的邏輯變得相當(dāng)清晰职员。
????????由于大佬的代碼經(jīng)過(guò)了封裝,有些細(xì)節(jié)被隱藏了跛溉,所以我們來(lái)做個(gè)小demo焊切,用谷歌官方的MVP實(shí)現(xiàn)方式來(lái)實(shí)現(xiàn)一個(gè) --模擬從服務(wù)器拉取信息展示到界面--? 的程序,更直觀的了解MVP芳室。
我的表演
????????先看一下最后呈獻(xiàn)的界面吧
? ? ? ? 界面布局很簡(jiǎn)單专肪,就一個(gè)TextView和一個(gè)Button,布局文件xml就不貼出來(lái)了堪侯。主要的功能是點(diǎn)一下獲取數(shù)據(jù)的按鈕嚎尤,模擬從服務(wù)器獲取數(shù)據(jù),然后在textview上顯示出來(lái)抖格。
? ? ? ? 下面的代碼結(jié)構(gòu)诺苹,由Activity(也就是View)咕晋、Presenter、Contract組成:
????????為了講解方便收奔,我們先來(lái)看一下MainContract里的內(nèi)容:
? ? ? ? 相當(dāng)簡(jiǎn)單掌呜,因?yàn)镃ontract是一個(gè)契約類,里面并沒(méi)有實(shí)現(xiàn)任何功能坪哄,只是寫明了Presenter和View分別要實(shí)現(xiàn)的接口质蕉,我在Presenter接口中定義了LoadData的方法,MainPresenter需要實(shí)現(xiàn)Presenter接口中的LoadData方法翩肌,來(lái)完成對(duì)數(shù)據(jù)從服務(wù)器的拉饶0怠;在接口View中定義了onDataLoaded的方法念祭,同樣兑宇,因?yàn)镸ainActivity應(yīng)用了接口View,因此需要對(duì)onDataLoaded方法進(jìn)行實(shí)現(xiàn)粱坤。
MainActivity:
????????MainActivity主要是界面組件的綁定隶糕,以及一些成員變量的初始化,可以看到我這里初始化了textview站玄、button還有一個(gè)presenter枚驻,之后界面關(guān)于數(shù)據(jù)的操作就通過(guò)presenter來(lái)實(shí)現(xiàn)。
? ? ? ? 我們可以看到株旷,這里重寫了onDataLoaded的方法再登,因?yàn)镸ainActivity implements了契約類中的View接口,因此需要將接口中的onDataLoaded方法實(shí)現(xiàn)晾剖,該方法的主要功能就是將presenter中獲取到的數(shù)據(jù)呈現(xiàn)在界面上锉矢,我們這邊是將數(shù)據(jù)顯示在界面的textview上。
MainPresenter:
????????MainPresenter是界面數(shù)據(jù)操作實(shí)現(xiàn)的地方钞瀑,他implements了契約類的Presenter接口沈撞,因此需要實(shí)現(xiàn)Presenter接口中定義的LoadData方法,該方法的功能是從服務(wù)器獲取數(shù)據(jù)然后回調(diào)給Activity(也就是View)雕什,我這邊偷懶了缠俺,沒(méi)有服務(wù)器獲取數(shù)據(jù),直接hard code出數(shù)據(jù)(嘻嘻)贷岸,嗯壹士,假裝獲取到了服務(wù)器端的數(shù)據(jù),然后調(diào)用View的onDataLoaded方法偿警,將所獲取到的數(shù)據(jù)傳遞到activity中躏救。這樣activity中就可以更新數(shù)據(jù)了。
? ? ? ? 奧,對(duì)了盒使,Presenter中必須有一個(gè)View的成員變量MainContract.View? mView;? 不然就不能調(diào)用view上面的方法了崩掘,mView的初始化,在Presenter變量創(chuàng)建的時(shí)候復(fù)制少办,可以在MainActivity中看到
? ? ? ? 看一下運(yùn)行的結(jié)果
? ? ? ? 由此苞慢,我們已經(jīng)實(shí)現(xiàn)了一個(gè)相當(dāng)相當(dāng)簡(jiǎn)單的基于MVP框架的app。
? ? ? ? 如果之后需要加功能英妓,只要在Contract中添加所需要功能的接口挽放,然后再在Presenter和Activity中分別實(shí)現(xiàn)就行。
? ? ? ? 比如說(shuō)我要新增一functionA蔓纠,執(zhí)行完后需要在View上做出相應(yīng)的界面改變辑畦。我們只需要這樣做:
1、在Contract中定義Presenter中functionA方法腿倚,以及View中的onFunctionAFinished方法
2纯出、在Presenter實(shí)現(xiàn)類中實(shí)現(xiàn)functionA具體方法,并調(diào)用更新界面的onFunctionAFinished
3敷燎、在Activity中實(shí)現(xiàn)onFunctionAFinished方法
? ? ? ? 這樣潦刃,又一個(gè)功能被添加了,是不是很方便懈叹,邏輯也很清晰。Activity只需負(fù)責(zé)界面更新的部分分扎,而數(shù)據(jù)的獲取澄成,全都交由Presenter來(lái)實(shí)現(xiàn),高內(nèi)聚低耦合畏吓,對(duì)于界面的維護(hù)和開(kāi)發(fā)相當(dāng)有幫助墨状。
? ? ? ? 當(dāng)然,以上只是MVP一個(gè)最簡(jiǎn)單不過(guò)的實(shí)現(xiàn)了菲饼,為了易于理解肾砂,我對(duì)很多基類的定義和封裝都去掉了,在實(shí)際的開(kāi)發(fā)中是不可能那么簡(jiǎn)單的宏悦,但是镐确,如果對(duì)于MVP的思想理解了,實(shí)現(xiàn)起來(lái)還是思路很清晰的饼煞。
? ? ? ? 以上源葫。
????????emmm......再貼上上面代碼的github地址吧,雖然沒(méi)幾行代碼砖瞧,但是不貼顯得不專業(yè)(嘿嘿
? ? ? ? 公司的開(kāi)發(fā)框架代碼我是不會(huì)貼的息堂,貼的是我的簡(jiǎn)單代碼(逃
? ? ? ? GitHub - reggie1996/mvp_demo: 簡(jiǎn)單MVP框架學(xué)習(xí)