最新消息:欢迎访问Android开发中文站!商务联系QQ:1304524325

Android MVP模式实战

新手入门 loading 1326浏览 1评论

一、什么是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 su=new SparseArray();

    @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显示的信息。

完整代码:http://download.csdn.net/detail/u011781521/9829343

转载请注明:Android开发中文站 » Android MVP模式实战

您必须 登录 才能发表评论!

网友最新评论 (1)

  1. 很详细,谢谢
    jwcs5202018-02-27 16:47