Android MVP架构模式简单示例

原文:https://blog.csdn.net/uyy203/article/details/78950718

MVP架构的概念

MVP(Model-View-Presenter)是从经典的模式MVC演变而来的,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会直接从Model中读取数据而不是通过 Controller。

image

View: 对应于Activity,负责View的绘制以及与用户交互
Model: 依然是业务逻辑和实体模型
Presenter: 负责完成View于Model间的交互

View不直接与Model交互,而是通过与Presenter交互来与Model间接交互。
Presenter与View的交互是通过接口来进行的。
通常View与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑。

MVP架构模式的简单实践

Version实体类

public class Version implements Serializable{
    //是否有新版本
    private String hasNewVersion;
    //新版本名
    private String versionName;
    //最新版本号
    private String versionCode;

    public void setHasNewVersion(String hasNewVersion) {
        this.hasNewVersion = hasNewVersion;
    }

    public String getHasNewVersion() {
        return hasNewVersion;
    }

    public String getVersionName() {
        return versionName;
    }

    public void setVersionName(String versionName) {
        this.versionName = versionName;
    }

    public String getVersionCode() {
        return versionCode;
    }

    public void setVersionCode(String versionCode) {
        this.versionCode = versionCode;
    }
}

主界面有两个TextView,一个用于显示版本名,一个用于显示版本号,还有一个按钮,点击按钮会触发请求,代码如下:

public class MvpActivity extends AppCompatActivity implements VersionView {

    private TextView versionName;
    private TextView versionCode;
    private VersionPresenter mVersionPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mvp);
        versionName = (TextView) findViewById(R.id.version_name);
        versionCode = (TextView) findViewById(R.id.version_code);
        mVersionPresenter = VersionPresenter.getInstance(this);

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mVersionPresenter.getNewVersion(getApplicationContext(), "local-url");
            }
        });
    }

    @Override
    public void showVersionNameAndDesc(Version version) {
        versionName.setText("最新版本名:" + version.getVersionName());
        versionCode.setText("最新版本号:" + version.getVersionCode());
    }

    @Override
    public void showToast(String msg) {
        Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
    }
}

该Activity实现了VersionView接口,这就是mvp中的view层,用于跟用户交互,显示数据。我们可以看到VersionPresenter的初始化,VersionPresenter属于presenter层,用于处理view与model层的通信,不让view直接操作model,可见用户点击按钮后,就通知VersionPresenter去获取版本信息,至于如何获取版本信息,presenter层会交给对应的model去进行处理,下面是VersionPresenter的代码:

public class VersionPresenter extends IPresenter {
    private static VersionPresenter mVersionPresenter;
    private VersionModel mVersionModel;
    private VersionView mVersionView;

    private VersionPresenter(IView view){
        this.mVersionView = (VersionView) view;
        this.mVersionModel = new VersionModel();
    }

    public static VersionPresenter getInstance(VersionView view){
        if (mVersionPresenter == null){
            synchronized (VersionPresenter.class){
                if (mVersionPresenter == null){
                    mVersionPresenter = new VersionPresenter(view);
                }
            }
        }
        return mVersionPresenter;
    }

    //获取版本信息
    public void getNewVersion(final Context context, String url){
        mVersionModel.getNewVersion(url, new VersionModel.VersionCallback() {
            @Override
            public void onVersionCallback(final Version version) {
                ((Activity)context).runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mVersionView.showVersionNameAndDesc(version);
                        if (version.getHasNewVersion().equals("true")){
                            mVersionView.showToast("App有新版本,请更新");
                        }
                    }
                });

            }
        });
    }

}

用户通知presenter后,presenter就把view的需求通知model层,数据操作交给model层去做具体实现,可以见到在VersionPresenter的getNewVersion方法中只是把view传过来的参数给到model,具体的网络请求交给VersionModel去实现,下面是VersionModel的具体实现:

public class VersionModel implements IModel {
    public interface VersionCallback {
        void onVersionCallback(Version version);
    }

    private HttpURLConnection httpURLConnection = null;
    private InputStream inputStream = null;
    private BufferedReader bufferedReader = null;

    public void getNewVersion(final String url, final VersionCallback versionCallback) {

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    httpURLConnection = (HttpURLConnection) new URL(url).openConnection();
                    httpURLConnection.connect();
                    inputStream = httpURLConnection.getInputStream();
                    bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
                    StringBuilder stringBuilder = new StringBuilder();
                    String tempLine = null;
                    while ((tempLine = bufferedReader.readLine()) != null) {
                        stringBuilder.append(tempLine).append("\n");
                    }
                    String data = stringBuilder.toString();
                    Log.e("data", data);
                    JSONObject jsonObject;
                    jsonObject = new JSONObject(data);
                    Version version=new Version();
                    version.setHasNewVersion("has_new_version");
                    version.setVersionCode(jsonObject.optString("version_code"));
                    version.setVersionName(jsonObject.optString("version_name"));
                    versionCallback.onVersionCallback(version);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        bufferedReader.close();
                        inputStream.close();
                    } catch (Exception e) {

                    }
                }
            }
        }).start();
    }
}

VersionModel去执行网络请求,获取到VersonView需要的数据然后回调到VersionPresenter,再由VersionPresenter通知VersonView去做UI的变化或者其他一些操作。纵观整个过程可以发现,view层和model层没有一丝耦合,这就是mvp架构模式的初衷,做到了松耦合,view,model,presenter每一层负责自身的工作,绝不越界。

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

推荐阅读更多精彩内容