前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MVP详细解析以及使用方法

MVP详细解析以及使用方法

作者头像
先知先觉
发布2019-01-21 16:22:43
8650
发布2019-01-21 16:22:43
举报
文章被收录于专栏:伟大程序猿的诞生

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不直接联系

代码语言:javascript
复制
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();
    }
}

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

代码语言:javascript
复制
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();
}

实现模型所需要的接口

代码语言:javascript
复制
public interface IUserModel {
    public void login(String username, String password, OnLoginListener loginListener);
}

实现模型所需要的接口

代码语言:javascript
复制
public interface OnLoginListener {
    void loginSuccess(User user);

    void loginFailed();
}

具体的业务在module完成

代码语言:javascript
复制
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();
    }
}

将View和modle关联到一起

代码语言:javascript
复制
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();
    }
}

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

代码语言:javascript
复制
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;
        }
    }
}
代码语言:javascript
复制
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();
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016年11月14日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • MVC
    • MVC 是一种框架模式而非设计模式。
      • MVC在Android中的实现
      • MVP
        • 区别
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档