實(shí)際開發(fā)中蝇恶,一個(gè)Activity中有許多的交互事件拳魁,這個(gè)時(shí)候Activity的代碼就顯得特別的龐大,整個(gè)activity顯得十分臃腫撮弧。Activity既實(shí)現(xiàn)視圖邏輯潘懊,又需要實(shí)現(xiàn)部分業(yè)務(wù)邏輯姚糊。
而我們需要activity是這樣的:
??負(fù)責(zé)發(fā)起處理和用戶交互的內(nèi)容,但又不負(fù)責(zé)具體的實(shí)現(xiàn)授舟;需要顯示什么救恨,不顯示什么,什么東西顯示多少释树,有個(gè)東西可以直接告訴他肠槽,Activity不再做復(fù)雜的邏輯處理;
【是時(shí)候展現(xiàn)MVP真正的實(shí)力了】
1.MVP奢啥,即View秸仙,Presenter,Model扫尺。
Model的工作就是完成對(duì)數(shù)據(jù)的操縱,數(shù)據(jù)的獲取炊汤、存儲(chǔ)正驻、數(shù)據(jù)狀態(tài)變化都是model層的任務(wù),如網(wǎng)絡(luò)請(qǐng)求抢腐,持久化數(shù)據(jù)增刪改查等任務(wù)姑曙。Activity/Fragment(View),只處理視圖相關(guān)迈倍,不做任何邏輯處理伤靠。Presenter,作為橋梁啼染,巧妙的將View和Model的具體實(shí)現(xiàn)連接了起來(lái)宴合。Presenter會(huì)根據(jù)需要調(diào)用model層的數(shù)據(jù),處理邏輯并在需要時(shí)
將回調(diào)傳入view層迹鹅。他們各司其職卦洽,互相搭配,實(shí)現(xiàn)了解耦斜棚,完全解放了Activity(或者是Fragment)阀蒂。這就是MVP 的優(yōu)勢(shì),使代碼結(jié)構(gòu)更加清晰弟蚀。
關(guān)于demo 就看最權(quán)威的吧---Google官網(wǎng)關(guān)于mvp的GitHub---demo
2.關(guān)于MVC和MVP
一句話概括MVP與MVC的區(qū)別:View能否直接操作Model
3.動(dòng)手操作
【項(xiàng)目目錄】
-
方式一:根據(jù)功能進(jìn)行分模塊 google的demo中就是按照這種方式劃分的
-
方式二:也可以按照model蚤霞,view,presenter這種情況進(jìn)行劃分組織目錄义钉,然后再按功能劃分
【base】
MVP不是沒有缺點(diǎn)的昧绣,在使用mvp的過程中,會(huì)多出很多類捶闸,每一個(gè)View(Activity或Fragment)都至少需要各自的Presenter和View接口滞乙,在加上他們各自的實(shí)現(xiàn)奏纪,不算model至少也要4個(gè)java文件,這樣一個(gè)稍有點(diǎn)規(guī)模的APP斩启,類就會(huì)變得異常的多序调,而每一個(gè)類的加載又會(huì)消耗資源;因此兔簇,相較于MVC发绢,這算是MVP最大的缺點(diǎn)了吧棠赛。
如何使用泛型和抽象優(yōu)化MVP 的結(jié)構(gòu)就變成了我們用好MVP的關(guān)鍵了巷挥。當(dāng)然黑滴,對(duì)于這個(gè)問題我們可以通過泛型參數(shù)毅贮、抽象父類的方式遮斥,將一些公用的Model及Presenter抽象出來(lái)录择。這應(yīng)該就是使用MVP架構(gòu)的精髓了勺阐。
定義基礎(chǔ)接口:BaseView和BasePresenter 的接口
我們可以將基礎(chǔ)的View層的操作(除了setPresenter绊谭,還可以根據(jù)自己的需求翻擒,比如網(wǎng)絡(luò)錯(cuò)誤顯示頁(yè)面氓涣、加載失敗頁(yè)面、列表為null陋气、正在加載等定義基礎(chǔ)方法)放在BaseView里面,對(duì)基礎(chǔ)的Presenter層的操作(比如獲取數(shù)據(jù))放在BasePresenter里面劳吠。減少后續(xù)代碼的重復(fù)。
MVP中Presenter和View層是需要交互的巩趁,這里通過setPresenter操作痒玩,我們也就可以獲得Presenter層的實(shí)例進(jìn)行交互了
public interface BaseView<T> {
void setPresenter(T presenter);
}
public interface BasePresenter {
void loadData();
}
【模塊】
接下來(lái)我們就要根據(jù)自己的業(yè)務(wù)模塊編寫了。
比如我們以登錄為例:
第一:我們需要定義一個(gè)協(xié)議類XXXContract --LoginContract
一個(gè)協(xié)議類將View和Presenter管理起來(lái)议慰,方便操作蠢古。
public interface LoginContract {
interface View extends BaseView<Presenter> {
void showLoginSuccessView(String avatar, String nickname);
void showFailureView();
}
interface Presenter extends BasePresenter {
void login();
}
}
第二:然后編寫View實(shí)現(xiàn)類 [XXXActivity/XXXFragment] 只與P層交互
public class LoginFragment extends Fragment implements LoginContract.View{
private LoginContract.Presenter mPresenter;
@Override
public void setPresenter(LoginContract.Presenter presenter) {
mPresenter = presenter;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPresenter=new LoginPresenter(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.login:
mPresenter.login();
break;
}
}
@Override
public void showLoginSuccessView(String avatar, String nickname) {
//登錄成功視圖處理
Glide.with(getActivity()).load(avatar).into(mAvatarView);
mNicknameView.setText(nickname);
}
......
......
}
第三:編寫Presenter的實(shí)現(xiàn)類,在這里進(jìn)行model層和view層的交互别凹。這里model層指的就是網(wǎng)絡(luò)請(qǐng)求對(duì)數(shù)據(jù)的獲取便瑟,而得到數(shù)據(jù)后是presenter去決定讓view顯示什么。它去做邏輯處理番川。
public class LoginPresenter implements LoginContract.Presenter {
private final LoginContract.View mLoginView;
public LoginPresenter(LoginContract.View loginView) {
mLoginView = loginView;
mLoginView.setPresenter(this);
}
@Override
public void login() {
NetManager.login(mLoginView.getContext(), new LoginCallback() {
@Override
public void onLoginSuccess(LoginObj response) {
mLoginView. showLoginSuccessView(response.getAvatar(),response.getNickName());
}
@Override
public void onLoginError(Exception obj) {
mLoginView.showFailureView();
}
});
}
}
第四:關(guān)于model層到涂,可能有些人該疑問,model在項(xiàng)目中是指哪里呢颁督,model層主要指的就是對(duì)數(shù)據(jù)的處理践啄,比如數(shù)據(jù)的獲取、存儲(chǔ)沉御、數(shù)據(jù)狀態(tài)變化都是model層的任務(wù)屿讽,比如Javabean、(你項(xiàng)目封裝的底層網(wǎng)絡(luò)庫(kù)、數(shù)據(jù)庫(kù))伐谈,持久化數(shù)據(jù)增刪改查等任務(wù)
要知道m(xù)odel不僅僅只是實(shí)體類的集合烂完,同時(shí)還包含關(guān)于數(shù)據(jù)的各種處理操作。
網(wǎng)絡(luò)請(qǐng)求的發(fā)起是在p層诵棵,網(wǎng)絡(luò)請(qǐng)求的回調(diào)根據(jù)成功與失敗等做邏輯處理也是在p層
但真正去請(qǐng)求獲取數(shù)據(jù)(比如okhttp抠蚣、或是自己封裝的HttpUtil)的復(fù)雜任務(wù)是在m層處理。