Android MVP模式实战教程

所属分类: 软件编程 / Android 阅读数: 36
收藏 0 赞 0 分享

一、什么是MVP

在网上找了些资料,整理如下:

  MVP是模型(Model)、视图(View)、主持人(Presenter)的缩写,分别代表项目中3个不同的模块。

  模型(Model):负责处理数据的加载或者存储,比如从网络或本地数据库获取数据等;
  视图(View):负责界面数据的展示,与用户进行交互;
  主持人(Presenter):相当于协调者,是模型与视图之间的桥梁,将模型与视图分离开来。

如下图所示,View与Model并不直接交互,而是使用Presenter作为View与Model之间的桥梁。其中Presenter中同时持有Viwe层以及Model层的Interface的引用,而View层持有Presenter层Interface的引用。当View层某个界面需要展示某些数据的时候,首先会调用Presenter层的某个接口,然后Presenter层会调用Model层请求数据,当Model层数据加载成功之后会调用Presenter层的回调方法通知Presenter层数据加载完毕,最后Presenter层再调用View层的接口将加载后的数据展示给用户。这就是MVP模式的整个核心过程。

在MVP模式里通常包含4个要素:

     (1)View:负责绘制UI元素、与用户进行交互(在Android中体现为Activity);
     (2)View interface:需要View实现的接口,View通过View interface与Presenter进行交互,降低耦合,方便进行单元测试;
     (3)Model:负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合);
     (4)Presenter:作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。

二、MVP模式的使用

上面一张简单的MVP模式的UML图,从图中可以看出,使用MVP,至少需要经历以下步骤:

1.创建IPresenter接口,把所有业务逻辑的接口都放在这里,并创建它的实现PresenterCompl(在这里可以方便地查看业务功能,由于接口可以有多种实现所以也方便写单元测试)

2.创建IView接口,把所有视图逻辑的接口都放在这里,其实现类是当前的Activity/Fragment

3.由UML图可以看出,Activity里包含了一个IPresenter,而PresenterCompl里又包含了一个IView并且依赖了Model。Activity里只保留对IPresenter的调用,其它工作全部留到PresenterCompl中实现

4.Model并不是必须有的,但是一定会有View和Presenter

三、一个简单的MVP示例

实现一个简单的用户登录

效果如下:

先来看看java文件的目录结构:

1.Baen包

UserBean

package com.example.mvpe.bean; 
 
/** 
 * Created by fendo on 2017/4/29. 
 */ 
 
public class UserBean { 
 private String username; 
 private String userpwd; 
 
 public UserBean() { 
 } 
 
 public UserBean(String username, String userpwd) { 
 this.username = username; 
 this.userpwd = userpwd; 
 } 
 
 public String getUsername() { 
 return username; 
 } 
 
 public void setUsername(String username) { 
 this.username = username; 
 } 
 
 public String getUserpwd() { 
 return userpwd; 
 } 
 
 public void setUserpwd(String userpwd) { 
 this.userpwd = userpwd; 
 } 
} 

2.Model包

IUserModel类

package com.example.mvpe.model; 
 
import com.example.mvpe.bean.UserBean; 
 
/** 
 * Created by fendo on 2017/4/29. 
 */ 
 
public interface IUserModel { 
 
 void setSid(int cid); 
 UserBean load(int sid); 
 void setUsername(String username); 
 void setUserpwd(String userpwd); 
} 

UserModelimp类

package com.example.mvpe.model; 
 
import android.provider.Settings; 
import android.util.Log; 
import android.util.SparseArray; 
 
import com.example.mvpe.bean.UserBean; 
 
/** 
 * Created by fendo on 2017/4/29. 
 */ 
 
public class UserModelimp implements IUserModel{ 
 
 private static final String ACTIVITY_TAG="UserModelimp"; 
 private String username; 
 private String userpwd; 
 private int sid; 
 private SparseArray<UserBean> su=new SparseArray<UserBean>(); 
 
 @Override 
 public void setSid(int cid) { 
 sid=cid; 
 } 
 
 @Override 
 public UserBean load(int sidy) { 
 sid=sidy; 
 UserBean ub=su.get(sid,new UserBean("not found", 
  "not found")); 
 return ub; 
 } 
 
 
 @Override 
 public void setUsername(String usernamey) { 
 username=usernamey; 
 } 
 
 @Override 
 public void setUserpwd(String userpwdy) { 
 userpwd=userpwdy; 
 UserBean usb=new UserBean(username,userpwd); 
 System.out.print(username+"----"+userpwd+"----"+sid); 
 Log.d(UserModelimp.ACTIVITY_TAG, "Start_OK"+username+"----"+userpwd+"----"+sid); 
 su.append(sid,usb); 
 } 
} 

3.persenter包

UserPersenter类

package com.example.mvpe.presenter; 
 
import android.util.Log; 
import android.view.View; 
 
import com.example.mvpe.bean.UserBean; 
import com.example.mvpe.model.IUserModel; 
import com.example.mvpe.model.UserModelimp; 
import com.example.mvpe.view.IUserView; 
 
 
 
/** 
 * Created by fendo on 2017/4/29. 
 */ 
 
public class UserPersenter { 
 
 private static final String ACTIVITY_TAG="UserPersenter"; 
 
 private IUserView iUserView; 
 private IUserModel iUserModel; 
 
 public UserPersenter(IUserView view){ 
 iUserView=view; 
 iUserModel=new UserModelimp(); 
 } 
 
 public void saveuser(int sid,String username,String userpwd){ 
 iUserModel.setSid(sid); 
 iUserModel.setUsername(username); 
 iUserModel.setUserpwd(userpwd); 
 } 
 
 public void loaduser(int sid){ 
 UserBean usb=iUserModel.load(sid); 
 Log.d(ACTIVITY_TAG, "loaduser: "+usb.getUsername()); 
 iUserView.setUsername(usb.getUsername()); 
 iUserView.setUserpwd(usb.getUserpwd()); 
 } 
 
} 

4.view包

IUserView类

package com.example.mvpe.view; 
 
import com.example.mvpe.bean.UserBean; 
 
/** 
 * Created by fendo on 2017/4/29. 
 */ 
 
public interface IUserView { 
 
 int getID(); 
 
 void setUsername(String username); 
 void setUserpwd(String userpwd); 
 
 String getUserpwd(); 
 String getUsername(); 
} 

UserActivity类

package com.example.mvpe.view; 
 
import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 
import android.widget.EditText; 
 
import com.example.mvpe.R; 
import com.example.mvpe.presenter.UserPersenter; 
import android.view.View.OnClickListener; 
import android.widget.Toast; 
 
/** 
 * Created by fendo on 2017/4/29. 
 */ 
 
public class UserActivity extends Activity implements OnClickListener,IUserView{ 
 
 private EditText userid; 
 private EditText username; 
 private EditText userpwd; 
 private Button read; 
 private Button write; 
 private UserPersenter usp; 
 
 @Override 
 protected void onCreate(Bundle savedInstanceState) { 
 super.onCreate(savedInstanceState); 
 usp=new UserPersenter(this); 
 setContentView(R.layout.activity_main); 
 findviewbyid(); 
 read.setOnClickListener(this); 
 write.setOnClickListener(this); 
 } 
 
 
 public void findviewbyid(){ 
 userid= (EditText) findViewById(R.id.userid); 
 username= (EditText) findViewById(R.id.usertext); 
 userpwd= (EditText) findViewById(R.id.userpwd); 
 read= (Button) findViewById(R.id.read); 
 write= (Button) findViewById(R.id.write); 
 } 
 
 @Override 
 public int getID() { 
 return Integer.parseInt(userid.getText().toString()); 
 } 
 
 @Override 
 public void setUsername(String usernamcc) { 
 username.setText(usernamcc); 
 } 
 
 @Override 
 public void setUserpwd(String userpw) { 
 userpwd.setText(userpw); 
 } 
 
 @Override 
 public String getUserpwd() { 
 return userpwd.getText().toString(); 
 } 
 
 @Override 
 public String getUsername() { 
 return username.getText().toString(); 
 } 
 
 
 @Override 
 public void onClick(View view) { 
 switch (view.getId()) { 
  case R.id.read : 
  usp.loaduser(getID()); 
  Toast.makeText(getApplicationContext(), "点击了读"+getID(), Toast.LENGTH_SHORT).show(); 
 
  break; 
  case R.id.write: 
  usp.saveuser(getID(),getUsername(),getUserpwd()); 
  Toast.makeText(getApplicationContext(), "点击了存"+getID()+"--"+getUsername()+"--"+getUserpwd(), Toast.LENGTH_SHORT).show(); 
  break; 
 } 
 } 
} 

可以看到View只负责处理与用户进行交互,并把数据相关的逻辑操作都扔给了Presenter去做。而Presenter调用Model处理完数据之后,再通过IUserView更新View显示的信息。

下载:源码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

Android控件系列之CheckBox使用介绍

CheckBox和Button一样,也是一种古老的控件,它的优点在于,不用用户去填写具体的信息,只需轻轻点击,缺点在于只有“是”和“否”两种情况,但我们往往利用它的这个特性,来获取用户的一些信息
收藏 0 赞 0 分享

Android控件系列之EditText使用方法

EditText是接受用户输入信息的最重要控件。通过前面课程的学习,您可能会猜到可以利用EditText.getText()获取它的文本,但真正的项目中,可能没那么简单,需要更多的限制,如文本长度限制,是否数字限制等等
收藏 0 赞 0 分享

Android控件系列之TextView使用介绍

TextView类似一般UI中的Label,TextBlock等控件,只是为了单纯的显示一行或多行文本,本文介绍了Android中文本控件TextView的用法和常用属性的用法
收藏 0 赞 0 分享

asynctask的用法详解

Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行,本文将为您介绍asynctask的用法
收藏 0 赞 0 分享

Android开发 旋转屏幕导致Activity重建解决方法

Android开发文档上专门有一小节解释这个问题。简单来说,Activity是负责与用户交互的最主要机制,接下来为您详细介绍
收藏 0 赞 0 分享

Notification与NotificationManager详细介绍

在Android系统中,发一个状态栏通知还是很方便的。下面我们就来看一下,怎么发送状态栏通知,状态栏通知又有哪些参数可以设置
收藏 0 赞 0 分享

android LinearLayout和RelativeLayout组合实现精确布局方法介绍

用android LinearLayout和RelativeLayout实现精确布局此方法适合很适合新人看
收藏 0 赞 0 分享

android listview优化几种写法详细介绍

这篇文章只是总结下getView里面优化视图的几种写法,需要的朋友可以参考下
收藏 0 赞 0 分享

Android应用开发SharedPreferences存储数据的使用方法

SharedPreferences是Android中最容易理解的数据存储技术,实际上SharedPreferences处理的就是一个key-value(键值对)SharedPreferences常用来存储一些轻量级的数据
收藏 0 赞 0 分享

Android之PreferenceActivity应用详解

为了引入这个概率 首先从需求说起 即:现有某Activity专门用于手机属性设置 那么应该如何做呢
收藏 0 赞 0 分享
查看更多