MVP模式最佳实践

阅读: 评论:0

MVP模式最佳实践

MVP模式最佳实践

1. 摘要

MVP(Model-View-Presenter)模式通过Presenter解决了Activity、Fragment等在MVC(Model-View-Controller)中太臃肿的问题。 Google给出了开源代码,向大家阐述了他们对于MVP模式的理解和建议: 。其中,todo-mvp分支则是最单纯(未使用其他任何框架)的MVP实现: /。 本文基于对todo-mvp分支的理解,以更加简单的代码,阐述了作者眼中的MVP模式。

2. MVP浅析

MVP由Model、View、Presenter组成。View最容易理解,即为Android中的各种widget控件。Presenter是为了让View和Model隔离而存在的。 Model并不仅仅是简单的bean,还包括了bean的一些业务逻辑,比如从服务器获取数据等。

3. Simplest MVP

本项目基于google的 todo-mvp,加上笔者的理解,写了一个查询天气情况的Android Demo。实现的功能非常简单:单击Button后,模拟网络查询当前温度,并使用Toast显示出来。如果不使用MVP,这个功能十几行代码即可实现。采用这个简单例子,旨在让初学者可以抓住MVP的本质。 代码可在: 。项目结构如图1所示:
                                           图1 SimplestMVP项目结构 其中,BaseView和BasePresenter均为interface。但也可以用abstract class。 BasePresenter在这里仅仅是一个接口,不包含其他方法。BasePresenter.java:
package com.afunx.mvp;public interface BasePresenter {
}
        BaseView中有一个setPresenter方法,通过这种方式,把View注入到Presenter中。BaseView.java:
package com.afunx.mvp;public interface BaseView<T> {void setPresenter(T presetner);
}
MainContract接口定义了MainContract.View接口和MainContract.Presenter。MainContract.java:
package com.afunx.mvp.main;import com.afunx.mvp.BasePresenter;
import com.afunx.mvp.BaseView;import com.afunx.mvp.main.bean.TemperatureBean;/*** This specifies the contract between the view and the presenter(View和Presenter的协议)*/public interface MainContract {interface View extends BaseView<Presenter> {/*** show present temperature(显示当前温度)** @param temperatureBean temperature bean(temperature bean对象)*/void showTemperature(TemperatureBean temperatureBean);}interface Presenter extends BasePresenter {/*** query present temperature from Internet and show it(从网络上查询当前温度,并显示它)*/void showPresentTemperature();}
}
TemperatureBean就是一个简单的记录温度的bean。TemperatureBean.java:
package com.afunx.mvp.main.bean;/*** TemperatureBean restore temperature in degree centigrade(TemperatureBean存储了气温的摄氏度)*/public class TemperatureBean {private int degree;public int getDegree() {return degree;}public void setDegree(int degree) {this.degree = degree;}
}
MainModel就是MVP中的Model,在复杂的项目中,MainModel也可以指某个模块。MainModel.java:
package com.afunx.del;import java.util.Random;import com.afunx.mvp.main.bean.TemperatureBean;
import com.afunx.mvp.main.presenter.MainPresenter;/*** Main Model represents model used by the Presenter ({@link MainPresenter})* ,simulate query present temperature from the Internet*/public class MainModel {/*** simulate query temperature from the Internet** @return TemperatureBean*/public TemperatureBean queryTemperature() {// simulate query from Servertry {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}// degree is in random [20,30)int degree = 20 + new Random().nextInt(10);TemperatureBean temperatureBean = new TemperatureBean();temperatureBean.setDegree(degree);return temperatureBean;}
}
MainPresenter实现了MainContract.Presenter接口,并在其构造器中调用mainView.setPresenter方法,把View注入到Presenter中。MainPresenter.java:
package com.afunx.mvp.main.presenter;import android.os.Handler;
import android.support.annotation.NonNull;import com.afunx.mvp.main.MainContract;
import com.afunx.mvp.main.bean.TemperatureBean;
import com.afunx.del.MainModel;
import com.afunx.mvp.main.view.MainActivity;/*** Listens to user actions from the UI ({@link MainActivity}), receives the data and updates the UI* (监听用户在UI上的动作,接收温度变化,并更新UI)*/public class MainPresenter implements MainContract.Presenter {@NonNullprivate final MainContract.View mMainView;private final MainModel mMainModel;public MainPresenter(@NonNull MainContract.View mainView) {mMainView = mainView;mMainModel = new MainModel();mainView.setPresenter(this);}@Overridepublic void showPresentTemperature() {// mainHandler is created in UI thread(mainHandler在UI线程中创建)final Handler mainHandler = new Handler();new Thread(){@Overridepublic void run() {// query temperature in non-UI thread(在非UI线程中,查询温度)final TemperatureBean temperatureBean = mMainModel.queryTemperature();mainHandler.post(new Runnable() {@Overridepublic void run() {// update View in UI thread(在UI线程中更新View)mMainView.showTemperature(temperatureBean);}});}}.start();}
}
MainActivity实现了MainContract.View接口。MainContract.View继承自BaseView<T>接口,故MainActivity实现了setPresenter方法。MainActivity在onCreate回调中,以new MainPresenter(this)的方式实现了View和Presenter的互相注入。对于任何一个新接触MVP的人来说,都有一点绕。多看一下 加粗红色部分解释和对应代码,慢慢就能理解了。MainActivity.java:
package com.afunx.mvp.main.view;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;import com.afunx.mvp.R;import com.afunx.mvp.main.MainContract;
import com.afunx.mvp.main.bean.TemperatureBean;
import com.afunx.mvp.main.presenter.MainPresenter;/*** UI for ({@link MainPresenter})* MainPresenter对应的UI*/
public class MainActivity extends AppCompatActivity implements MainContract.View, View.OnClickListener {private Button mBtnShowTemperature;private MainContract.Presenter mMainPresenter;@Overridepublic void setPresenter(MainContract.Presenter presetner) {mMainPresenter = presetner;}@Overrideprotected void onCreate(Bundle savedInstanceState) {Create(savedInstanceState);setContentView(R.layout.activity_main);new MainPresenter(this);mBtnShowTemperature = (Button) findViewById(R.id.btn_show_temperature);mBtnShowTemperature.setOnClickListener(this);}@Overridepublic void onClick(View v) {if (v == mBtnShowTemperature) {mMainPresenter.showPresentTemperature();}}@Overridepublic void showTemperature(TemperatureBean temperatureBean) {int celsius = Degree();String format = getString(R.string.present_temperature_text);String text = String.format(format, celsius);Toast.makeText(this, text, Toast.LENGTH_SHORT).show();}
}
MainActivity对应的布局文件l:
<?xml version="1.0" encoding="utf-8"?>
<straint.ConstraintLayout xmlns:android=""xmlns:app=""xmlns:tools=""android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.afunx.mvp.main.view.MainActivity"><Buttonandroid:id="@+id/btn_show_temperature"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="8dp"android:layout_marginEnd="8dp"android:layout_marginStart="8dp"android:layout_marginTop="8dp"android:text="@string/show_temperature"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /></straint.ConstraintLayout>
       最终效果如图2:
                                             图2 SimplestMVP效果gif                                                                         


4. 引用

[1] 
[2] 

本文发布于:2024-02-05 04:19:27,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170723960762980.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:模式   MVP
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23