MVP

Android MVP模式

  1. MVC模式 & 缺點(diǎn)
    MVC讶迁,全稱Model-View-Controller,即模型-視圖-控制器鬓长。 具體如下:
  • View:對(duì)應(yīng)于布局文件
  • Model:業(yè)務(wù)邏輯和實(shí)體模型
  • Controllor:對(duì)應(yīng)于Activity

缺點(diǎn)
MVC模式下實(shí)際上就是Activty與Model之間交互谒拴,View完全獨(dú)立出來(lái)了。
View對(duì)應(yīng)于布局文件涉波,其實(shí)能做的事情特別少英上,實(shí)際上關(guān)于該布局文件中的數(shù)據(jù)綁定的操作,事件處理的代碼都在Activity中啤覆,造成了Activity既像View又像Controller苍日,使得Activity變得臃腫。


在這里插入圖片描述
  1. MVP模式 & 優(yōu)點(diǎn)
    MVP窗声,全稱 Model-View-Presenter相恃,即模型-視圖-層現(xiàn)器。具體如下:
  • View 對(duì)應(yīng)于Activity笨觅,負(fù)責(zé)View的繪制以及與用戶交互
  • Model 依然是業(yè)務(wù)邏輯和實(shí)體模型
  • Presenter 負(fù)責(zé)完成View于Model間的交互

優(yōu)點(diǎn)
MVP模式通過(guò)Presenter實(shí)現(xiàn)數(shù)據(jù)和視圖之間的交互拦耐,簡(jiǎn)化了Activity的職責(zé)耕腾。同時(shí)即避免了View和Model的直接聯(lián)系,又通過(guò)Presenter實(shí)現(xiàn)兩者之間的溝通杀糯。
MVP模式減少了Activity的職責(zé)幽邓,簡(jiǎn)化了Activity中的代碼,將復(fù)雜的邏輯代碼提取到了Presenter中進(jìn)行處理火脉,模塊職責(zé)劃分明顯牵舵,層次清晰。與之對(duì)應(yīng)的好處就是倦挂,耦合度更低畸颅,更方便的進(jìn)行測(cè)試。


在這里插入圖片描述
  1. MVP & MVC 區(qū)別

    在這里插入圖片描述

    MVC中是允許Model和View進(jìn)行交互的方援,而MVP中很明顯没炒,Model與View之間的交互由Presenter完成。還有一點(diǎn)就是Presenter與View之間的交互是通過(guò)接口的犯戏。

  2. MVP模式 典例 —— 登錄案例
    結(jié)構(gòu)圖

    在這里插入圖片描述

    1.Model層
    在本例中送火,M0del層負(fù)責(zé)對(duì)從登錄頁(yè)面獲取地帳號(hào)密碼進(jìn)行驗(yàn)證(一般需要請(qǐng)求服務(wù)器進(jìn)行驗(yàn)證,本例直接模擬這一過(guò)程)先匪。 從上圖的包結(jié)構(gòu)圖中可以看出种吸,Model層包含內(nèi)容:
    ①實(shí)體類bean
    ②接口,表示Model層所要執(zhí)行的業(yè)務(wù)邏輯
    ③接口實(shí)現(xiàn)類呀非,具體實(shí)現(xiàn)業(yè)務(wù)邏輯坚俗,包含的一些主要方法
    下面以代碼的形式一一展開。
    ①實(shí)體類bean

public class User {
    private String password;
    private String username;

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String toString() {
        return "User{" +
                "password='" + password + '\'' +
                ", username='" + username + '\'' +
                '}';
    }
}

封裝了用戶名岸裙、密碼猖败,方便數(shù)據(jù)傳遞。
②接口

public interface LoginModel {
    void login(User user, OnLoginFinishedListener listener);
}

其中OnLoginFinishedListener 是presenter層的接口降允,方便實(shí)現(xiàn)回調(diào)presenter恩闻,通知presenter業(yè)務(wù)邏輯的返回結(jié)果,具體在presenter層介紹剧董。
③接口實(shí)現(xiàn)類

public class LoginModelImpl implements LoginModel {
    @Override
    public void login(User user, final OnLoginFinishedListener listener) {
        final String username = user.getUsername();
        final String password = user.getPassword();
        new Handler().postDelayed(new Runnable() {
            @Override public void run() {
                boolean error = false;
                if (TextUtils.isEmpty(username)){
                    listener.onUsernameError();//model層里面回調(diào)listener
                    error = true;
                }
                if (TextUtils.isEmpty(password)){
                    listener.onPasswordError();
                    error = true;
                }
                if (!error){
                    listener.onSuccess();
                }
            }
        }, 2000);
    }
}

實(shí)現(xiàn)Model層邏輯:延時(shí)模擬登陸(2s)幢尚,如果用戶名或者密碼為空則登陸失敗,否則登陸成功送滞。
2.View層
視圖:將Modle層請(qǐng)求的數(shù)據(jù)呈現(xiàn)給用戶侠草。一般的視圖都只是包含用戶界面(UI),而不包含界面邏輯犁嗅,界面邏輯由Presenter來(lái)實(shí)現(xiàn)。
從上圖的包結(jié)構(gòu)圖中可以看出晤碘,View包含內(nèi)容:
①接口褂微,上面我們說(shuō)過(guò)Presenter與View交互是通過(guò)接口功蜓。其中接口中方法的定義是根據(jù)Activity用戶交互需要展示的控件確定的。
②接口實(shí)現(xiàn)類宠蚂,將上述定義的接口中的方法在Activity中對(duì)應(yīng)實(shí)現(xiàn)具體操作式撼。
下面以代碼的形式一一展開。
①接口

public interface LoginView {
    //login是個(gè)耗時(shí)操作求厕,我們需要給用戶一個(gè)友好的提示著隆,一般就是操作ProgressBar
    void showProgress();

    void hideProgress();
   //login當(dāng)然存在登錄成功與失敗的處理,失敗給出提示
    void setUsernameError();

    void setPasswordError();
   //login成功呀癣,也給個(gè)提示
    void showSuccess();
}

上述5個(gè)方法都是presenter根據(jù)model層返回結(jié)果需要view執(zhí)行的對(duì)應(yīng)的操作美浦。
②接口實(shí)現(xiàn)類
即對(duì)應(yīng)的登錄的Activity,需要實(shí)現(xiàn)LoginView接口项栏。

public class LoginActivity extends AppCompatActivity implements LoginView, View.OnClickListener {
    private ProgressBar progressBar;
    private EditText username;
    private EditText password;
    private LoginPresenter presenter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        progressBar = (ProgressBar) findViewById(R.id.progress);
        username = (EditText) findViewById(R.id.username);
        password = (EditText) findViewById(R.id.password);
        findViewById(R.id.button).setOnClickListener(this);
       //創(chuàng)建一個(gè)presenter對(duì)象浦辨,當(dāng)點(diǎn)擊登錄按鈕時(shí),讓presenter去調(diào)用model層的login()方法沼沈,驗(yàn)證帳號(hào)密碼
        presenter = new LoginPresenterImpl(this);
    }

    @Override
    protected void onDestroy() {
        presenter.onDestroy();
        super.onDestroy();
    }

    @Override
    public void showProgress() {
        progressBar.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideProgress() {
        progressBar.setVisibility(View.GONE);
    }

    @Override
    public void setUsernameError() {
        username.setError(getString(R.string.username_error));
    }

    @Override
    public void setPasswordError() {
        password.setError(getString(R.string.password_error));
    }

    @Override
    public void showSuccess() {
         progressBar.setVisibility(View.GONE);
        Toast.makeText(this,"login success",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onClick(View v) {
        User user = new User();
        user.setPassword(password.getText().toString());
        user.setUsername(username.getText().toString());
        presenter.validateCredentials(user);
    }

}

View層實(shí)現(xiàn)Presenter層需要調(diào)用的控件操作流酬,方便Presenter層根據(jù)Model層返回的結(jié)果進(jìn)行操作View層進(jìn)行對(duì)應(yīng)的顯示。
3.Presenter層
Presenter是用作Model和View之間交互的橋梁列另。 從上圖的包結(jié)構(gòu)圖中可以看出芽腾,Presenter包含內(nèi)容:
①接口,包含Presenter需要進(jìn)行Model和View之間交互邏輯的接口页衙,以及上面提到的Model層數(shù)據(jù)請(qǐng)求完成后回調(diào)的接口晦嵌。
②接口實(shí)現(xiàn)類,即實(shí)現(xiàn)具體的Presenter類邏輯拷姿。
下面以代碼的形式一一展開惭载。
①接口

public interface OnLoginFinishedListener {
    void onUsernameError();

    void onPasswordError();

    void onSuccess();
}

當(dāng)Model層得到請(qǐng)求的結(jié)果,需要回調(diào)Presenter層响巢,讓Presenter層調(diào)用View層的接口方法描滔。

public interface LoginPresenter {
    void validateCredentials(User user);

    void onDestroy();
}

登陸的Presenter 的接口,實(shí)現(xiàn)類為L(zhǎng)oginPresenterImpl踪古,完成登陸的驗(yàn)證含长,以及銷毀當(dāng)前view。
②接口實(shí)現(xiàn)類

public class LoginPresenterImpl implements LoginPresenter, OnLoginFinishedListener {
    private LoginView loginView;
    private LoginModel loginModel;

    public LoginPresenterImpl(LoginView loginView) {
        this.loginView = loginView;
        this.loginModel = new LoginModelImpl();
    }

    @Override
    public void validateCredentials(User user) {
        if (loginView != null) {
            loginView.showProgress();
        }

        loginModel.login(user, this);
    }

    @Override
    public void onDestroy() {
        loginView = null;
    }

    @Override
    public void onUsernameError() {
        if (loginView != null) {
            loginView.setUsernameError();
            loginView.hideProgress();
        }
    }

    @Override
    public void onPasswordError() {
        if (loginView != null) {
            loginView.setPasswordError();
            loginView.hideProgress();
        }
    }

    @Override
    public void onSuccess() {
        if (loginView != null) {
            loginView.showSuccess();
        }
    }
}

由于presenter完成二者的交互伏穆,那么肯定需要二者的實(shí)現(xiàn)類(通過(guò)傳入?yún)?shù)拘泞,或者new)。
presenter里面有個(gè)OnLoginFinishedListener枕扫, 其在Presenter層實(shí)現(xiàn)陪腌,給Model層回調(diào),更改View層的狀態(tài), 確保 Model層不直接操作View層诗鸭。

核心流程總結(jié)
View與Model并不直接交互染簇,而是使用Presenter作為View與Model之間的橋梁。其中Presenter中同時(shí)持有View層的Interface的引用以及Model層的引用强岸,而View層持有Presenter層引用锻弓。當(dāng)View層某個(gè)界面需要展示某些數(shù)據(jù)的時(shí)候勇边,首先會(huì)調(diào)用Presenter層的引用竿滨,然后Presenter層會(huì)調(diào)用Model層請(qǐng)求數(shù)據(jù),當(dāng)Model層數(shù)據(jù)加載成功之后會(huì)調(diào)用Presenter層的回調(diào)方法通知Presenter層數(shù)據(jù)加載情況辽旋,最后Presenter層再調(diào)用View層的接口將加載后的數(shù)據(jù)展示給用戶妓盲。本例模式:

在這里插入圖片描述

一般模式:


在這里插入圖片描述
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末杂拨,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子本橙,更是在濱河造成了極大的恐慌扳躬,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件甚亭,死亡現(xiàn)場(chǎng)離奇詭異贷币,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)亏狰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門役纹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人暇唾,你說(shuō)我怎么就攤上這事促脉。” “怎么了策州?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵瘸味,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我够挂,道長(zhǎng)旁仿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任孽糖,我火速辦了婚禮枯冈,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘办悟。我一直安慰自己尘奏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布病蛉。 她就那樣靜靜地躺著炫加,像睡著了一般瑰煎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上琢感,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天丢间,我揣著相機(jī)與錄音探熔,去河邊找鬼驹针。 笑死,一個(gè)胖子當(dāng)著我的面吹牛诀艰,可吹牛的內(nèi)容都是我干的柬甥。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼其垄,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼苛蒲!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起绿满,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤臂外,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后喇颁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體漏健,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年橘霎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蔫浆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡姐叁,死狀恐怖瓦盛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情外潜,我是刑警寧澤原环,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站处窥,受9級(jí)特大地震影響嘱吗,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜碧库,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一柜与、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嵌灰,春花似錦弄匕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春城丧,著一層夾襖步出監(jiān)牢的瞬間延曙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工亡哄, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留枝缔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓蚊惯,卻偏偏與公主長(zhǎng)得像愿卸,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子截型,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

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

  • MVP模式已經(jīng)火了很長(zhǎng)時(shí)間趴荸,似乎已經(jīng)火的過(guò)時(shí)。雖然現(xiàn)在MVVM風(fēng)頭正勁宦焦,但是MVP模式使用簡(jiǎn)單方便发钝,并使得耦合度降...
    Ruheng閱讀 14,210評(píng)論 3 47
  • 1 介紹 1.1 背景 ??MVP,全稱 Model-View-Presenter波闹,要說(shuō)MVP那就不得不說(shuō)一說(shuō)它的...
    Gs1993閱讀 1,488評(píng)論 0 4
  • 久違的晴天酝豪,家長(zhǎng)會(huì)。 家長(zhǎng)大會(huì)開好到教室時(shí)舔痪,離放學(xué)已經(jīng)沒(méi)多少時(shí)間了寓调。班主任說(shuō)已經(jīng)安排了三個(gè)家長(zhǎng)分享經(jīng)驗(yàn)。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,523評(píng)論 16 22
  • 今天感恩節(jié)哎锄码,感謝一直在我身邊的親朋好友夺英。感恩相遇!感恩不離不棄滋捶。 中午開了第一次的黨會(huì)痛悯,身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,564評(píng)論 0 11
  • 可愛(ài)進(jìn)取,孤獨(dú)成精重窟。努力飛翔载萌,天堂翱翔。戰(zhàn)爭(zhēng)美好巡扇,孤獨(dú)進(jìn)取扭仁。膽大飛翔,成就輝煌厅翔。努力進(jìn)取乖坠,遙望,和諧家園刀闷⌒鼙茫可愛(ài)游走...
    趙原野閱讀 2,727評(píng)論 1 1