Android中MVP模式的了解及实例

Android中MVP的由来

在了解MVP之前我相信很多人已经学习过MVC这个框架了!MVP的诞生可以说是建立在MVC在安卓某些不足的方面

MVC简介

.M对应Model,代表业务数据

.V对应View,代表视图

.C对应Controller,代表控制器。

具体逻辑结构如下图所示:


来自百度百科

MVC框架将视图和数据分离,在WEB领域有着十分广泛的应用。

用户通过界面组件进行操作,也就是View层,相应的动作会传递给控制器也就是Controller层,而Controller根据自己的业务逻辑去操作数据层也就是Model,

而最终数据层的变化会同步更新到视图层。


MVC的主要目的是为了视图和数据分离,这对于开发大型软件来说更方便进行模块的划分,提高编码速度与质量。


Android中的MVC

Android世界中也经常运用到MVC模式。 

Activity对应视图界面也就是View层。 

数据库文件,Sharedprefrence,内存缓冲,磁盘缓冲等数据内容对应Model层。 

而Controller控制层基本上也由Activity层面来进行。

Android中mvc中基本动作流程

假设我们现在有这么一个需求,需要在一个界面上显示当天的天气,不仅如此,还可以通过列表项选择以往某一天的天气。 

mvc架构开发的话,大概是这样。

在layout制定相应的布局文件,然后显示在Activity上,用于显示天气信息。这对应于View层,这里的View并不是Android中开发中的组件view而是对视图的统称.

Activity在onCreate方法或者onResume方法去服务器获取数据,或者通过界面上的某个按钮之类去启动获取服务器数据的任务,这里就对应到View—>Controller,只不过这里的View和Controller对是由Activity来完成。

Controller获取到了数据之后,分别存在,内存、磁盘和数据库中,并且数据获取成功或者失败后,Activity界面需要同步更新状态。这由对应上面流程中的Controller—>Model 和Model—->View。


(这是你或许会想:MVC这思路不是很清晰吗??为什么还要整一个MVP呢?因为Android的特殊性,

使得Activity对应了MVC中的V和C,同时担任两个角色,就不符合软件设计原则的“单一职责”原则。但现实中是很多的APP代码中有这么的处境,特别是Androi原生的很多系统APK,

某些Activity动则几千行代码。 况且,随着项目的深入发展,很多逻辑很越来越复杂,Activity处理的东西也会越来越多,代码越来越臃肿。这样一来维护起来的代价就会越来越高,

这是因为View的变化会引起Controller的很多变化,反之亦然。用一句大白话来说明就是–某一段代码的变动会引起很多其他相关联的代码的改动。

MVP是基于MVC的,它的架构图如下: 



图片来自百度百科



.M(Model) 数据相关层

.V(View) 视图层,如Activity上的布局

.P(Presenter) 纽带层,用来连接Model与View.

MVP开发在Android中的基本流程 

1. View层定义View.interface,用来定义View的行为。一般由Activity或者是Fragment来实现这个接口,它定义了View视图的各种变化,如设置Textview,加载对话框,更新进度条等。


2. Model层定义Modle.interface,这个是用来定义数据层发生变化时的通知接口,因为Model不能直接与View交互,所以它与Presenter交互,然后再通过Presenter间接达到与View的交互。 


3. Presenter翻译的意思是主持人,也就是主持场合,控制节奏的意思。在这时Presenter就负责具体的业务逻辑,请求数据,把数据送到Model,或者监听Model的数据变化,接受View

层的动作,负责通过通知View层的视图变化。

类似于王者荣耀中的打野位(掌控节奏)


MVP实践

先是我们需要些的代码有哪几项:




而我们需要实现的效果则是:


1



2


3

例子本身是非常简单的,可以说用MVP简直是多此一举。

主要是说学习这个思想。

具体代码如下:


----------------------------------WetherPresenter-------------------------------


package com.example.acer.mvpdome.presenter;

import com.example.acer.mvpdome.model.IWetherImpl;

import com.example.acer.mvpdome.model.IWetherModel;

import com.example.acer.mvpdome.view.IWetherView;

public class WetherPresenter

{

IWetherModelmModel;

IWetherViewmView;

////因为Presenter持有View的引用,所以在这里要将View.interface注入到Presenter当中。

    public WetherPresenter(IWetherView mView) {

this.mView = mView;

mModel =new IWetherImpl();

}

//供View层调用,用来请求天气数据

    public void requestWetherInfo(){

getNetworkInfo();

}

private void getNetworkInfo()

{

new Thread(new Runnable() {

@Override

            public void run()

{

try {

//打开等待对话框

                showWaitingDialog();

//模拟网络耗时

                Thread.sleep(6000);

String info ="21度,晴转多云";

//保存到Model层

                saveInfo(info);

//从Model层获取数据,为了演示效果,实际开发中根据情况需要。

                  String localinfo = localInfo();

//通知View层改变视图

                  updateWetherInfo(localinfo);

}

catch (InterruptedException e)

{

e.printStackTrace();

}

//取消对话框

                dissmissWaitingDialog();

}

}).start();

}

private void showWaitingDialog(){

if (mView !=null) {

mView.showWaitingDialog();

}

}

private void dissmissWaitingDialog(){

if (mView !=null) {

mView.dissmissWaitingDialog();

}

}

private void updateWetherInfo(String info){

if (mView !=null) {

mView.onInfoUpdate(info);

}

}

private String localInfo(){

return mModel.getInfo();

}

private void saveInfo(String info){

mModel.setInfo(info);

}

}


---------------------------------IWetherView---------------------------

package com.example.acer.mvpdome.view;

public interface IWetherView

{

/**1.显示天气信息

*2.显示获取信息等待对话框

* 3.取消显示对话框

*/

    public void  showWaitingDialog();

public void dissmissWaitingDialog();

public void onInfoUpdate(String info);

}


---------------------------MainActivity------------------------------


package com.example.acer.mvpdome.view;

import android.app.ProgressDialog;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.util.Log;

import android.view.View;

import android.widget.Button;

import android.widget.TextView;

import com.example.acer.mvpdome.R;

import com.example.acer.mvpdome.presenter.WetherPresenter;

public class MainActivityextends AppCompatActivityimplements IWetherView

{

WetherPresentermPresenter;

private TextViewmTvInfo;

private Buttonmbtn;

private ProgressDialogmDialog;

@Override

    protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mPresenter =new WetherPresenter(this);

mbtn=findViewById(R.id.mbtn);

mTvInfo=findViewById(R.id.mTvInfo);

mbtn.setOnClickListener(new View.OnClickListener() {

@Override

            public void onClick(View view) {

mPresenter.requestWetherInfo();

}

});

}

@Override

    public void showWaitingDialog()

{

runOnUiThread(new Runnable() {

@Override

            public void run()

{

if (mDialog !=null &&mDialog.isShowing())

{

mDialog.dismiss();

}

mDialog = ProgressDialog.show(MainActivity.this,"","正在获取中...");

}

});

}

@Override

    public void dissmissWaitingDialog() {

runOnUiThread(new Runnable() {

@Override

              public void run()

{

if (mDialog !=null &&mDialog.isShowing())

{

mDialog.dismiss();

}

}

});

}

@Override

    public void onInfoUpdate(final String info)

{

Log.d("-------------","onInfoUpdate: "+info);

runOnUiThread(new Runnable() {

@Override

              public void run()

{

mTvInfo.setText(info);

}

});

}

}


---------------------------------------IWetherModel-------------------------------------------


package com.example.acer.mvpdome.model;

public interface IWetherModel

{

//提供数据

    public  String  getInfo();

//存储数据

    public void setInfo(String info);

}

----------------------------------------------IWetherImpl--------------------------------------


package com.example.acer.mvpdome.model;

public class IWetherImplimplements IWetherModel

{

private Stringinfo;

@Override

    public String getInfo()

{

return info;

}

@Override

    public void setInfo(String info)

{

this.info=info;

}

}


分析:

这里可以看成三个人:主持人甲,拿着数据的人乙,负责展示的人丙。


首先是拿着数据的人乙,和model区别不大,接口,实现类!一路过基本上多可以理解


然后是负责展示的人丙,展示的方式的实现,接口,问题也不大!


最后主持人甲要做的事情就多了,因为要同时对View和Model对接,所以内部必须持有它们的接口引用

而Presenter也要开发API供View调用。 

所以Presenter要有requestWetherInfo()方法,剩下的基本都是它对其他两个的方法的调用!!

有兴趣的朋友可以继续深入研究

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容