android MVP使用

http://www.cnblogs.com/wanqieddy/p/4478690.html

上面有个例子,重点参考 

http://www.cnblogs.com/mybkn/archive/2012/04/12/2443676.html

http://www.cnblogs.com/cqumonk/p/4392285.html

目录

一、MVP的介绍

二、为什么要用MVP

三、MVP与MVC的不同

四、利用MVP进行Android开发的例子

一、MVP的介绍

随着UI创建技术的功能越来越强,UI层也履行着越来越多的职责。为了更好的细分视图(View)与模型(Model)的功能,让View更专注于数据的可视化

和与用户的交互,同时让Model只关系数据的处理,基于MVC概念的MVP模式产生了。

MVP有下面的四个要素:

1.View:负责绘制UI元素,与用户进行交互,在Android中体现为Activity。

2.View interface:需要View实现的接口,View通过View interface 与 Presenter进行交互,降低耦合,方便进行单元测试。

3.Model: 负责存储,检索,操纵数据(有时也实现 一个Model interface用来降低耦合)。

4.Presenter:作为View 与 Model交互的中间纽带,处理与用户交互的逻辑。

如下图

二、为什么要用MVP

      随着界面和逻辑的复杂度不断提升,Activity类的职责越来越重。因此我们将其中复杂的逻辑处理移到另外的一个类(Presenter)中时,Activit其实就是MVP

中的View ,它负责UI元素的初始化,建立UI元素与Presenter的关系(Listener之类),同时自己也会处理一些简单的逻辑(复杂的逻辑交由Presenter处理)。

     另外,回想一下我们在开发android应用的时候,都是怎么对代码 逻辑进行测试的?每次我们都要将应用安装到android真机上,然后通过用户操作进行测试,

这浪费了我们大量的时间。而在MVP模式中,处理复杂逻辑的Presenter是通过 interface 与 View(Activity)进行交互的,所以我们可以通过自定义类实现这个

interface来模拟Activity 的行为对 Presenter进行单元测试,节省了大量的测试时间。

三、MVP与MVC的不同

MVP

  • View 不直接与Model进行交互,而是通过与 Presenter 交互来与Model 间接交互。
  • Presenter 与View的交互是通过接口来实现 的,利于添加单元测试。
  • 通常View 与 Presenter 是一对一的,但复杂的View可以有多个 Presenter 。

MVC

  • View可以与Model直接交互。
  • Controller 是基于行为的,并且可以被多个View共享 。
  • 可以负责决定显示哪个View 

四、利用MVP进行Android开发的例子

首先是目录结构 

可以看到Model与 View都是通过 interface与Presenter进行交互的,这样降低了耦合,还降低了测试的难度。

  • 定义一个UserBean来保存用户信息
package com.chuiyuan.bean;

public class UserBean {
	private String firstName ;
	private String lastName ;
	
	public UserBean (String firstName , String lastName ){
		this.firstName = firstName ;
		this.lastName = lastName ;
	}
	public String getFirstName() {
		return firstName;
	}

	public String getLastName() {
		return lastName;
	}
}
  • View接口

由需求可以知道,View可以对ID ,firstname ,lastname这三个 EditText进行读操作,对firstname ,lastname 还可以进行写操作,由此我们定义接口如下

public interface IUserView {
	int getID();
	String getLastName () ;
	String getFirstName ();
	void setFirstName (String firstName );
	void setLastName (String lastName ) ;
}
  • Model接口 

同样,Model也要对这三个字段进行读写操作,并存储在某个载体内(这时我们暂时不关心,可以是内存,文件,数据结构等,但对于Presenter和View没有

影响),定义 IUserModel的接口

public interface IUserModel {
	void setID(int id ) ;
	void setFirstName(String firstName );
	void setLastName (String lastName);
	
	UserBean load(int id ) ;//通过id读取信息
}
  • Model功能的实现 
public class UserModel implements IUserModel {

	private String mFristName;
	private String mLastName;
	private int mID;
	private SparseArray<UserBean> mUsererArray = new SparseArray<UserBean>();

	@Override
	public void setID(int id) {
		// TODO Auto-generated method stub
		mID = id;
	}

	@Override
	public void setFirstName(String firstName) {
		// TODO Auto-generated method stub
		mFristName = firstName;
	}

	@Override
	public void setLastName(String lastName) {
		// TODO Auto-generated method stub
		mLastName = lastName;
		UserBean UserBean = new UserBean(mFristName, mLastName);
		mUsererArray.append(mID, UserBean);
	}

	@Override
	public UserBean load(int id) {
		// TODO Auto-generated method stub
		mID = id;
		UserBean userBean = mUsererArray.get(mID, new UserBean("not found",
				"not found"));
		return userBean;

	}

}

  

  • Presenter

这时,Presenter就可以通过接口与Model/View进行交互了。

public class UserPresenter {
	private IUserView mUserView ;
	private IUserModel mUserModel ;
	
	public UserPresenter (IUserView view){
		mUserView = view ;
		mUserModel = new UserModel();
	}
	public void saveUser (int id, String firstName ,String lastName ){
		mUserModel.setID(id) ;
		mUserModel.setFirstName(firstName) ;
		mUserModel.setLastName(lastName) ;
	}
	public void loadUser (int id ){  //加载并更新显示
		UserBean user = mUserModel.load(id) ;
		mUserView.setFirstName(user.getFirstName()) ;
		mUserView.setLastName(user.getLastName()) ;
	}
}
  • UserViewActivity

 UserViewActivity实现了IUserView及View.OnClickListener接口,同时有一个UserPresenter成员变量.

package com.chuiyuan.view;

import com.chuiyuan.presenter.UserPresenter;
import com.example.mvptest.R;
import com.example.mvptest.R.id;
import com.example.mvptest.R.layout;

import android.R.integer;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;


public class UserViewActivity extends ActionBarActivity implements OnClickListener, IUserView {
	private EditText mFirstNameEt , mLastNameEt, mIdEt ;
	private Button mSaveBtn ,mLoadBtn ;
	private UserPresenter mUserPresenter ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findWidget();
        mUserPresenter = new UserPresenter(this ) ;
        mSaveBtn.setOnClickListener(this ) ;
        mLoadBtn.setOnClickListener(this );
    }


    private void findWidget() {
		mFirstNameEt = (EditText)findViewById(R.id.first_name_edt);
		mLastNameEt = (EditText)findViewById(R.id.last_name_edt) ;
		mIdEt = (EditText)findViewById(R.id.id_edt ) ;
		
		mSaveBtn = (Button)findViewById(R.id.saveButton) ;
		mLoadBtn= (Button)findViewById(R.id.loadButton) ;
	}

	@Override
	public int getID() {
		// TODO Auto-generated method stub
		return Integer.parseInt(mIdEt.getText().toString());
	}


	@Override
	public String getLastName() {
		// TODO Auto-generated method stub
		return mLastNameEt.getText().toString();
	}


	@Override
	public String getFirstName() {
		// TODO Auto-generated method stub
		return mFirstNameEt.getText().toString();
	}


	@Override
	public void setFirstName(String firstName) {
		mFirstNameEt.setText(firstName) ;
	}


	@Override
	public void setLastName(String lastName) {
		mLastNameEt.setText(lastName) ;
	}


	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.saveButton:
			mUserPresenter.saveUser(getID(),
					getFirstName(), getLastName()) ;
			break;
		case R.id.loadButton:
			mUserPresenter.loadUser(getID()) ;
			break ;

		default:
			break;
		}
	}
}

可以看到,View只负责处理与用户的交互,而将数据相关的逻辑都交给了Presenter去做,而Presenter调用Model处理完数据后,而通过IUserView更新

View的显示的消息。

整体结构如下

原文地址:https://www.cnblogs.com/chuiyuan/p/4578603.html