虽然mvp在如今已经不算新事物的,但是我觉得来介绍下还是很有必要的。先说原理吧。
MVP 全称:Model-View-Presenter ;
MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。**
mvp
这段介绍太过于官方了,在我看来:原来mvc中view(activity、fragment等)里的逻辑处理太过臃肿,耦合性也很高。mvp中吧数据处理放在了单独的Model里,再通过Presenter来控制model和view的交互。再精简一点,我觉得可以解释成:把view里的事分给model和Presenter去做!
优点
- 模型与视图完全分离,我们可以修改视图而不影响模型
- 可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter内部
- 我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁。
- 如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑
缺点
- 代码量变多(前期)
- 如果view的需求改变,很有可能会导致Presenter也需要改变
mvp就说到这,下面介绍一个比较好用的插件——MVPHelper
如何安装
直接在setting 的plugin选项搜索安装即可
如何使用
在 Contract 类或者 Presenter 类内部,点击 Generate 菜单或使用快捷键 Alt + Insert, 选择 Mvp Helper 即可生成对应文件.
你也可以直接去 github查看详细步骤
我这里使用的模式是Contract 模式
这是我项目的结构
下面开始介绍我完成mvp Demo
需求
我要完成的是首页倒计时进入主页面,点击倒计时可以提前进入主页
功能比较简单,单足够体现mvp模式了
思路
在mvc模式下,拿到需求不用多想,直接就在activity里开干了。但在mvp下需要构思下Presenter 和model要未完成的工作,这是一个不同之处
Contract集合
在通过插件创建完架子后,我们得到了WelcomeContract这个接口集合类
public interface WelcomeContract {
interface Model {
void startCount(WelcomePresenter welcomePresenter);
void endCount(WelcomePresenter welcomePresenter);
}
interface View {
void changeText(String s);
void onSuccess();
}
interface Presenter {
void onSuccess();
void onStop();
void changeText(String s);
}
}
这里我定义了三层里面要用到的接口:
1.Model
*startCount 创建倒计时
*endCount 点击跳过
其方法中带有Presenter是因为需要把结果通过Presenter传递给view
@Override
public void startCount(final WelcomePresenter welcomePresenter) {
if (null == countDownTimer){
countDownTimer = new CountDownTimer(3200,1000) {
@Override
public void onTick(long millisUntilFinished) {
LogUtil.d("dxw",""+millisUntilFinished/1000);
welcomePresenter.changeText("跳过"+(millisUntilFinished/1000));
}
@Override
public void onFinish() {
welcomePresenter.onSuccess();
}
};
}
countDownTimer.start();
}
@Override
public void endCount(WelcomePresenter welcomePresenter) {
if (null != countDownTimer){
countDownTimer.cancel();
welcomePresenter.onSuccess();
}
}
我们可以看到model中调用了changeText和onSuccess方法。
2.View
*changeText 修改textview文字
*onSuccess 倒计时自然结束后跳转到主页
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
ButterKnife.bind(this);
activity = WelcomeActivity.this;
welcomePresenter = new WelcomePresenter(this);
welcomePresenter.startTime();
}
@OnClick(R.id.welcome_time)
public void onViewClicked() {
welcomePresenter.onStop();
}
@Override
public void changeText(String s) {
welcomeTime.setText(s);
}
@Override
public void onSuccess() {
finish();
intent = new Intent(activity, MainActivity.class);
startActivity(intent);
}
在onCreate中,先new得到welcomePresenter,再调用welcomePresenter暴露的方法startTime,startTime执行了WelcomeModel写好的倒计时逻辑。
onViewClicked点击事件执行了welcomePresenter持有的onStop方法,onStop执行了
WelcomeModel写好的终端年倒计时逻辑。
changeText得到了welcomePresenter 持有的WelcomeModel倒计时过程中回调过来的数据,更新倒计时文字。
onSuccess 跳转页面,提供给welcomePresenter ,welcomePresenter 持有后创建onSuccess供给WelcomeModel在自然结束或者提前结束倒计时的时候调用,达到跳转效果。
3.Presenter
*changeText 修改跳过view的文字
- onStop 点击跳过执行
*onSuccess 倒计时自然结束的处理
Presenter中做了下面几件事
- 得到view和model的引用,统一处理
- 暴露一个方法用于view来开始执行整个事件
public class WelcomePresenter implements WelcomeContract.Presenter {
private WelcomeContract.View mView;
private WelcomeModel welcomeModel;
public WelcomePresenter(WelcomeContract.View view){
mView = view;
welcomeModel = new WelcomeModel();
}
@Override
public void onSuccess(){
mView.onSuccess();
}
@Override
public void changeText(String s) {
mView.changeText(s);
}
@Override
public void onStop() {
welcomeModel.endCount(this);
}
public void startTime(){
welcomeModel.startCount(this);
}
}
带参构造方法WelcomePresenter得到view和welcomeModel 后,
在 onSuccess 和changeText执行 view想要完成的事情(跳转和给textview赋值)
在onStop执行model 需要提前结束的事件(取消倒计时)。
暴露一个startTime方法给view在特定时候开始整个事件
至此,完成。
小结:
我是通过介绍WelcomeContract中三层用到的接口来叙述如何完成这个demo的。在我看来mvp是先分工后开发
最后分享我项目的地址,后期会在此基础上完成mvp+dragger+retrofit+rxjava 这一 目前主流的开发模式
网友评论