這一定是最簡單的MVP+Retrofit

說明:不講原理何暮,不講優(yōu)化俄精,就是干

目標:學會如何搭建最最基本的mvp架構(gòu)

簡介

我承認畫圖不是我的強項

MVP是MVC衍生出來的架構(gòu)改橘,現(xiàn)在也比較成熟了,用的人也多了谦趣,面試也會考了疲吸,所以你必須要知道了

M:數(shù)據(jù)層(數(shù)據(jù)庫,文件前鹅,網(wǎng)絡等)

V:UI層(Activity摘悴,F(xiàn)ragment,View及其子類舰绘,Adapter及其子類)

P:中介(作用:關(guān)聯(lián)V和M)

經(jīng)過思想斗爭蹂喻,我覺得理論上的東西解釋再多不如代碼敲一遍葱椭,下面用一個用戶登陸功能講解如何搭建MVP架構(gòu),順便簡單用下Retrofit網(wǎng)絡請求庫(別怕都有注釋)總之口四,MVP記住一個核心思想:V層就只做UI的操作孵运,所有的業(yè)務處理和數(shù)據(jù)處理都交給P層(不然要你何用)就相當于把Activity里你寫的眾多網(wǎng)絡請求和數(shù)據(jù)處理代碼統(tǒng)統(tǒng)提取封裝到P里了

MVP結(jié)構(gòu)

api:Retrofit專用的,就兩行代碼蔓彩,和mvp無關(guān)掐松,待會給你看

bean:登陸的實體類,和mvp無關(guān)

login:可以看出是按功能分包粪小。他比平時見到的多出來兩個類大磺,一個是 LoginPresenter(P層),一個是 LoginContract(契約接口類探膊,用于將P和V接口封裝到一起)他們是mvp重要的組成部分

架構(gòu)圖如下:

思路

mvp結(jié)構(gòu)實現(xiàn)分三步:

一杠愧,搞一個接口契約類Contract,內(nèi)含V接口和P接口

二逞壁,搞一個實現(xiàn)V接口的view類

三流济,搞一個實現(xiàn)P接口的presenter類

第一步:

搞一個接口契約類Contract,內(nèi)含V接口和P接口腌闯。V接口里面放的是UI更新方法(V接口的實現(xiàn)類用到的方法)绳瘟;P接口里面放的是網(wǎng)絡請求,數(shù)據(jù)讀取姿骏,文件讀取等具體的業(yè)務操作方法(P接口的實現(xiàn)類用到的方法)

從動態(tài)圖可以看到糖声,一共有三個地方有UI界面變化

①點擊登陸展示等待加載遮罩

②登陸成功或者失敗后取消等待加載遮罩

③取消等待加載遮罩的同時吐司

所以V接口里會有三個UI更新方法,那么就在V接口寫三個方法唄分瘦,值得注意的是setPresenter方法只是用來把V層和P層關(guān)聯(lián)的蘸泻,本身與UI更新無關(guān),但是必須要有的

P接口在本例中只需要實現(xiàn)一個登陸按鈕觸發(fā)的網(wǎng)絡請求就可以啦嘲玫,所以只有一個方法

由此可見悦施,契約類Contract把V和P接口封裝在了一塊,而V和P接口又把具體的view和presenter用到的方法封裝在了一塊

/**

* 包含View和Presenter的契約接口

* Created by wangjiong on 2017/12/7.

*/

publicinterfaceLoginContract{

/**

* 與UI相關(guān)去团,與view相關(guān)操作

*/

interfaceView{

// 定義Presenter

voidsetPresenter();

// 展示等待加載頁面

voidshowLoading();

// 隱藏等待加載頁面

voidhideLoading();

// 顯示登陸信息

voidshowLoginInfo(String msg);

}

/**

* 與業(yè)務相關(guān)

*/

interfacePresenter{

/**

* 登陸

* @param userId? ? ? 用戶id

* @param userPassword 密碼

*/

voidlogin(String userId, String userPassword);

}

}

第二步:

搞一個實現(xiàn)V接口的view類抡诞。本例中的view類就是LoginActivity。首先實現(xiàn)接口所有的方法是必須的土陪,然后這里有兩個地方需要注意

一昼汗,我們是在實現(xiàn)V層接口setPresenter方法里通過LoginPresenter的構(gòu)造方法將LoginActivity傳遞過去的(LoginPresenter是P的實現(xiàn)類),這里要記得主動調(diào)用一下setPresenter方法觸發(fā)初始化presenter這個事

二旺坠,就是所謂的MVP中V層和P層分隔開乔遮,UI和業(yè)務分隔開。比如本例登陸按鈕的點擊事件取刃,他并不是我們平時看到的直接擼網(wǎng)絡請求代碼蹋肮,而是調(diào)用了P層里的的方法出刷,說人話就是把網(wǎng)絡請求一大堆代碼封裝了一個方法放到了P層那個類里頭了,我們在調(diào)用的時候傳需要用到的參數(shù)就行了坯辩。你說坑不坑馁龟,這點玩意說的那么高大尚

/**

* MVP層中的View層

*/

publicclassLoginActivityextendsAppCompatActivityimplementsLoginContract.View{

privateLoginPresenter mPresenter;

privateEditText mEtName, mEtPwd;

privateLinearLayout mLayoutLoading;

@Override

protectedvoidonCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_login);

setPresenter();// 初始化presenter(很重要!不能說重寫就不管了漆魔,一定要在view初始化調(diào)用此方法)

mEtName = findViewById(R.id.et_name);// 用戶名

mEtPwd = findViewById(R.id.et_pwd);// 密碼

mLayoutLoading = findViewById(R.id.layout_loading);// 遮罩層

findViewById(R.id.btn_login).setOnClickListener(newView.OnClickListener() {// 登陸按鈕

@Override

publicvoidonClick(View view){// 點擊登陸不是直接請求網(wǎng)絡坷檩,而是通過presenter請求網(wǎng)絡,然后將請求回來的數(shù)據(jù)交給view來更新

mPresenter.login(mEtName.getText().toString().trim(), mEtPwd.getText().toString().trim());

}

});

}

@Override

publicvoidsetPresenter(){

mPresenter =newLoginPresenter(this);// 一是為了實例化presenter改抡,二是通過構(gòu)造方法將view實例傳遞給presenter

}

@Override

publicvoidshowLoading(){// 展示遮罩層

mLayoutLoading.setVisibility(View.VISIBLE);

}

@Override

publicvoidhideLoading(){// 隱藏遮罩層

mLayoutLoading.setVisibility(View.GONE);

}

@Override

publicvoidshowLoginInfo(String msg){// 吐司登陸信息

Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();

}

}

第三步:

搞一個實現(xiàn)P接口的presenter類矢炼。本例中presenter類就是LoginPresenter,可以看到他就一個構(gòu)造方法(用來關(guān)聯(lián)V層并獲取view實例化對象)和一個請求網(wǎng)絡數(shù)據(jù)的方法阿纤。高能預警:網(wǎng)絡請求前UI頁面需要展示一個遮罩層句灌,所以調(diào)用了view的showLoading方法,請求結(jié)束后UI頁面需要取消遮罩并吐司欠拾,所以調(diào)用了view的hideLoading方法和showLoginInfo方法

/**

* MVP中的P層

* Created by wangjiong on 2017/12/7

*/

publicclassLoginPresenterimplementsLoginContract.Presenter{

privateLoginContract.View mView;

publicLoginPresenter(LoginContract.View view){// 獲取到view的實例化對象

this.mView = view;

}

@Override

publicvoidlogin(String userId, String password){

mView.showLoading();// 調(diào)用view的展示遮罩方法(view用來更新具體的UI)

// 網(wǎng)絡請求(可以自己封裝一個網(wǎng)絡庫)

Retrofit retrofit =newRetrofit.Builder()

.baseUrl("http://192.168.1.101:8080/merclienttest/")// 請求的url

.addConverterFactory(GsonConverterFactory.create())// 設(shè)置Gson為實體類解析工具

.build();

LoginApi loginApi = retrofit.create(LoginApi.class);// 傳入一個接口類并返回此類的實例對象

Call call = loginApi.login(userId, password);// 調(diào)用類中定義的login方法

call.enqueue(newCallback() {// retrofit異步請求

@Override

publicvoidonResponse(Call call, Response response){

mView.hideLoading();// 調(diào)用view的隱藏遮罩方法(view用來更新具體的UI)

mView.showLoginInfo(response.body().getMsg());// 調(diào)用view的吐司方法(view用來更新具體的UI)

}

@Override

publicvoidonFailure(Call call, Throwable t){

mView.hideLoading();

}

});

}

}

全劇終

媽個雞這是啥玩意胰锌?完了?哈哈哈藐窄,沒錯這就是MVP资昧。就是這么簡單。只需要記住一個核心思想V層僅僅是處理UI頁面的(只管化妝接客荆忍,拉皮條找老鴇子P)格带,業(yè)務邏輯放在P層去處理(網(wǎng)絡請求,數(shù)據(jù)庫东揣,文件等)践惑,P處理完之后再調(diào)用一下V層已經(jīng)寫好的對應更新UI的方法即可

擴展

沒忘記Retrofit哦,簡單介紹下使用方法

分三步:

一嘶卧,搞一個接口類Api

二,搞一個對應的實體類bean

三凉袱,調(diào)用Retrofit方法請求網(wǎng)絡

第一步:搞一個Api接口芥吟。本例中是LoginApi

第一行代碼 @GET("login") 這個Get就代表get請求,如果換成Post那就代表post請求专甩。login代表接口名(接口名需要后臺提供)

第二行代碼?Call login(@Query("userId") String userId, @Query("password") String password); 其中 login 代表自己定義的一個方法钟鸵,名字隨便起(小駝峰式命名),@Query("userId") 代表接口中有個名為 userId 的參數(shù)涤躲,?String userId 代表給這個參數(shù)傳值棺耍,值為userId(名字隨便起)

/**

* 登陸接口

* Created by wangjiong on 2017/12/7.

*/

publicinterfaceLoginApi{

@GET("login")//get請求login接口(接口名需要后臺提供)

Calllogin(@Query("userId") String userId, @Query("password") String password);// 聲明一個login的方法(隨便寫),兩個string形參种樱,并返回一個實體類LoginBean

}

沒反應過來蒙袍?

jsonObject.put("userId",userId) 這樣寫懂了吧俊卤,第一個userId是接口里的參數(shù)名,第二個userId是你傳的字符串值害幅,名字隨便搞的消恍,叫啥都行

你也可以@Query("userId") String myUserId這就等價于

jsonObject.put("userId",myUserId??)? 這里只是為了說明問題,所以不必太在意細節(jié)

第二步以现,搞一個對應的實體類bean狠怨。這個對應本例中的LoginBean。推薦用GsonFormat插件自動生成邑遏,啥佣赖?沒聽過,你又不是妹子记盒,百度吧

publicclassLoginBean{

/**

* code : 200

* msg : 登陸成功

*/

privateString code;

privateString msg;

publicStringgetCode(){

returncode;

}

publicvoidsetCode(String code){

this.code = code;

}

publicStringgetMsg(){

returnmsg;

}

publicvoidsetMsg(String msg){

this.msg = msg;

}

}

第三步憎蛤,調(diào)用Retrofit方法請求網(wǎng)絡。做完上面兩步孽鸡,就可以正常調(diào)用了蹂午,咋用?你又不是妹子彬碱,參考LoginPresenter吧

/**

* MVP中的P層

* Created by wangjiong on 2017/12/7

*/

publicclassLoginPresenterimplementsLoginContract.Presenter{

privateLoginContract.View mView;

publicLoginPresenter(LoginContract.View view){// 獲取到view的實例化對象

this.mView = view;

}

@Override

publicvoidlogin(String userId, String password){

mView.showLoading();// 調(diào)用view的展示遮罩方法(view用來更新具體的UI)

// 網(wǎng)絡請求(可以自己封裝一個網(wǎng)絡庫)

Retrofit retrofit =newRetrofit.Builder()

.baseUrl("http://192.168.1.101:8080/merclienttest/")// 請求的url

.addConverterFactory(GsonConverterFactory.create())// 設(shè)置Gson為實體類解析工具

.build();

LoginApi loginApi = retrofit.create(LoginApi.class);// 傳入一個接口類并返回此類的實例對象

Call call = loginApi.login(userId, password);// 調(diào)用類中定義的login方法

call.enqueue(newCallback() {// retrofit異步請求

@Override

publicvoidonResponse(Call call, Response response){

mView.hideLoading();// 調(diào)用view的隱藏遮罩方法(view用來更新具體的UI)

mView.showLoginInfo(response.body().getMsg());// 調(diào)用view的吐司方法(view用來更新具體的UI)

}

@Override

publicvoidonFailure(Call call, Throwable t){

mView.hideLoading();

}

});

}

}

源碼地址:https://github.com/GodJiong/mvp

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末豆胸,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子巷疼,更是在濱河造成了極大的恐慌晚胡,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嚼沿,死亡現(xiàn)場離奇詭異估盘,居然都是意外死亡,警方通過查閱死者的電腦和手機骡尽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門遣妥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人攀细,你說我怎么就攤上這事箫踩。” “怎么了谭贪?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵境钟,是天一觀的道長。 經(jīng)常有香客問我俭识,道長慨削,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮缚态,結(jié)果婚禮上磁椒,老公的妹妹穿的比我還像新娘。我一直安慰自己猿规,他們只是感情好衷快,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著姨俩,像睡著了一般蘸拔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上环葵,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天调窍,我揣著相機與錄音,去河邊找鬼张遭。 笑死邓萨,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的菊卷。 我是一名探鬼主播缔恳,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼洁闰!你這毒婦竟也來了歉甚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤扑眉,失蹤者是張志新(化名)和其女友劉穎纸泄,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腰素,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡聘裁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了弓千。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片衡便。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖洋访,靈堂內(nèi)的尸體忽然破棺而出砰诵,到底是詐尸還是另有隱情,我是刑警寧澤捌显,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站总寒,受9級特大地震影響扶歪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一善镰、第九天 我趴在偏房一處隱蔽的房頂上張望妹萨。 院中可真熱鬧,春花似錦炫欺、人聲如沸乎完。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽树姨。三九已至,卻和暖如春桥状,著一層夾襖步出監(jiān)牢的瞬間帽揪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工辅斟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留转晰,地道東北人。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓士飒,卻偏偏與公主長得像查邢,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子酵幕,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容