MVP详细解析以及使用方法

[置顶] MVP详细解析以及使用方法

标签: androidmvpmvcjava
1060人阅读 评论(0) 收藏 举报
本文章已收录于:
分类:

github地址:https://github.com/libin7278/MPV-example
需要结合开源项目理解MVP并逐步学会使用,本开源项目正在逐步完善中

MVP(Module View Controller)是MVC的演进版本,所以首先介绍一下MVC(Module View Presenter)

MVC

MVC 是一种框架模式而非设计模式。

框架:用来对软件设计进行分工。
设计模式:小技巧,对具体问题提出解决方案,太高代码复用率,降低耦合度。

MVC在Android中的实现

View层一般采用XMl文件进行界面的描述;
Module则对应本地数据文件或者网络获取的数据体;
Controller部分则由Activity承担;
这个框架并非我们自己完成的,而是由framework给我们搭建好并提供给我们。

MVP

解除了View和Module的耦合,同时又带来了良好的可扩展性,可测试性。
使用MVP的好处:UI可能随时改变,如果业务逻辑耦合在View中,UI修改会导致我们重新抽离View中的业务逻辑。MVP刚好帮我们完成了逻辑抽离。

区别

(1)MVC中是允许Model和View进行交互的,而MVP中很明显,Model与View之间的交互由Presenter完成。
(2)还有一点就是Presenter与View之间的交互是通过接口的。
首先看一下实现了MVP的Activity出来的效果,这是一个最简单的用户名登录

MVC特点
1.用户可以向View发送指令,再由View直接要求Modle改变状态
2.用户可以直接向Controller发送指令,再由Controller发送View
3.Controller起到事路由的作用,同时业务逻辑都部署在Controller
这里写图片描述

MVVM特点
View和Model进行双向绑定,两者之间有一方发生变化则会反映到另一方上。ViewModle要做的只是业务逻辑处理,以及修改View或者Modle的状态。
这里写图片描述

MVP特点
View更新通过Presenter,View和Modle不直接联系
这里写图片描述

package com.mvp.libin.mvp_example;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.mvp.libin.mvp_example.base.MVPBaseActivity;
import com.mvp.libin.mvp_example.bean.User;
import com.mvp.libin.mvp_example.presenter.UserLoginPresenterB;
import com.mvp.libin.mvp_example.view.IViewUserLogin;

/**
 * Created by libin on 16/11/9.
 */

public class ActivityBUserLogin extends MVPBaseActivity<IViewUserLogin,UserLoginPresenterB>implements IViewUserLogin {
    private EditText et_usernam,et_userpassword;
    private ProgressBar pb;
    private Button btn_login,btn_clear;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        findViewById();

        //登录
        btn_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mPresenter.login();
            }
        });

        //清除
        btn_clear.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mPresenter.clear();
            }
        });

    }

    @Override
    protected UserLoginPresenterB createPresenter() {
        return new UserLoginPresenterB(this);
    }

    private void findViewById() {
        et_userpassword = (EditText) findViewById(R.id.et_userpassword);
        et_usernam = (EditText) findViewById(R.id.et_usernam);

        btn_login = (Button) findViewById(R.id.btn_login);
        btn_clear = (Button) findViewById(R.id.btn_clear);

        pb = (ProgressBar) findViewById(R.id.pb);
    }

    @Override
    public String getUserName() {
        return et_usernam.getText().toString();
    }

    @Override
    public String getPassword() {
        return et_userpassword.getText().toString();
    }

    @Override
    public void clearUserName() {
        et_usernam.setText("");
    }

    @Override
    public void clearPassword() {
        et_userpassword.setText("");
    }

    @Override
    public void showLoading() {
        pb.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideLoading() {
        pb.setVisibility(View.INVISIBLE);
    }

    @Override
    public void toMainActivity(User user) {
        Toast.makeText(this, user.getUsername() + " login success , to MainActivity", Toast.LENGTH_SHORT).show();
    }


    @Override
    public void showFailedError() {
        Toast.makeText(this, " login failed ", Toast.LENGTH_SHORT).show();
    }
}

    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105

首先考虑一下View 我们这个登录都需要啥?
然后定义出所有需要的方法

package com.mvp.libin.mvp_example.view;

import com.mvp.libin.mvp_example.bean.User;

/**
 * Created by libin on 16/11/8.
 */

public interface IViewUserLogin {
    String getUserName();

    String getPassword();

    void clearUserName();

    void clearPassword();

    void showLoading();

    void hideLoading();

    void toMainActivity(User user);

    void showFailedError();
}

    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

实现模型所需要的接口

public interface IUserModel {
    public void login(String username, String password, OnLoginListener loginListener);
}
    
    
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

实现模型所需要的接口

public interface OnLoginListener {
    void loginSuccess(User user);

    void loginFailed();
}
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

具体的业务在module完成

public class UserModel implements IUserModel {
    @Override
    public void login(final String username, final String password, final OnLoginListener loginListener) {
        //模拟子线程耗时操作
        new Thread()
        {
            @Override
            public void run()
            {
                try
                {
                    Thread.sleep(2000);
                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
                //模拟登录成功
                if ("123".equals(username) && "123".equals(password))
                {
                    User user = new User();
                    user.setUsername(username);
                    user.setPassword(password);
                    loginListener.loginSuccess(user);
                } else
                {
                    loginListener.loginFailed();
                }
            }
        }.start();
    }
}
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

将View和modle关联到一起

public class UserLoginPresenterB extends BasePresenter<IViewUserLogin> {
    private IUserModel userBiz;
    private IViewUserLogin userLoginView;
    private Handler mHandler = new Handler();

    public UserLoginPresenterB(IViewUserLogin userLoginView)
    {
        this.userLoginView = userLoginView;
        this.userBiz = new UserModel();
    }

    public void login()
    {
        userLoginView.showLoading();
        userBiz.login(userLoginView.getUserName(), userLoginView.getPassword(), new OnLoginListener()
        {
            @Override
            public void loginSuccess(final User user)
            {
                //需要在UI线程执行
                mHandler.post(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        userLoginView.toMainActivity(user);
                        userLoginView.hideLoading();
                    }
                });

            }

            @Override
            public void loginFailed()
            {
                //需要在UI线程执行
                mHandler.post(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        userLoginView.showFailedError();
                        userLoginView.hideLoading();
                    }
                });

            }
        });
    }

    public void clear()
    {
        userLoginView.clearUserName();
        userLoginView.clearPassword();
    }
}
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

接下来我们来看一下基类的实现,之所以要用弱引用,是因为Presenter经常执行一些耗时的操作,而presenter持有Activity的强引用,如果在请求结束之前Activity被销毁,网络请求还没有返回,导致presenter一直持有activity的对象,使得activity对象无法被回收,此时发生内存泄漏。

package com.mvp.libin.mvp_example.base;

import java.lang.ref.Reference;
import java.lang.ref.WeakReference;

/**
 * Created by libin on 16/11/8.
 */

public class BasePresenter<T> {
    protected Reference<T> mViewRef;  //View接口类型的弱引用

    /**
     * 建立关联
     * @param view
     */
    public void attachView(T view){
        mViewRef = new WeakReference<T>(view);
    }

    /**
     * 获取View
     * @return
     */
    protected T getView(){
        return mViewRef.get();
    }

    /**
     * 判断是否与View建立关联
     * @return
     */
    public boolean isViewAttach(){
        return mViewRef != null && mViewRef.get() != null;
    }

    /**
     * 解除关联
     */
    public void detechView(){
        if(mViewRef != null){
            mViewRef.clear();
            mViewRef = null;
        }
    }
}

    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
public abstract class MVPBaseActivity<V,T extends BasePresenter<V>> extends Activity{
    protected T mPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mPresenter = createPresenter(); //创建Presenter

        mPresenter.attachView((V) this); //View与Presenter建立关联
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mPresenter.detechView();  //解除关联
    }

    protected abstract T createPresenter();
}
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
13
1
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值