MVC --> MVP :

将Activity的View和Controller双重职责分离,Activity单纯负责View逻辑,Presenter层处理Model和View层的交互逻辑,Model层处理数据逻辑。

换言之,MVP类似于MVC++,解决分离不彻底的问题。

同时MVP也有一些值得讨论的地方:

  • Presenter层与View层是通过接口进行交互,接口粒度控制存在问题。粒度小,接口量过大;粒度大,单一职能性不好。
  • Presenter只是解决了功能分离的问题,复杂业务单个类代码臃肿问题,仍需要分离多个Presenter - View处理同一个复杂页面。

瑕不掩瑜,MVP仍然是很好的一套Android前端框架。


文件结构如下:

MVP简单架构

当然实际项目中不可能这样分包,这里只是单纯MVP结构划分的效果。

M、V、P 接口以及具体的实现

Model:这里只有处理登录逻辑。持有Presenter

package com.example.mvpdemo.model;

/**
 * Model层 数据逻辑处理
 */
public interface IUserBiz {
    void login(String username, String password);
}
package com.example.mvpdemo.model;

import com.example.mvpdemo.bean.UserBean;
import com.example.mvpdemo.presenter.ILoginPresenter;

/**
 * Model层 具体的数据逻辑实现
 */
public class UserBiz implements IUserBiz {

    private ILoginPresenter mPresenter;

    public UserBiz(ILoginPresenter mPresenter) {
        this.mPresenter = mPresenter;
    }

    @Override
    public void login(String username, String password) {
        // 假设进行了异步登录
        if ("fengz".equals(username) && "123456".equals(password)) {
            // 持久化用户信息
            UserBean userBean = new UserBean();
            userBean.setUsername(username);
            userBean.setPassword(password);
            mPresenter.loginSuccess(userBean);
        } else {
            mPresenter.loginFail("假设网络异常吧!");
        }
    }
}

View:对应登录逻辑,页面的不同效果,以及获取页面数据。持有Presenter

package com.example.mvpdemo.view;

import com.example.mvpdemo.bean.UserBean;

/**
 * View层 分离UI逻辑
 */
public interface ILoginView {
    
    void toSuccessPage(UserBean user);

    void showErrMessage(String message);
}
/**
 * View层 处理ui逻辑
 */
public class MainActivity extends AppCompatActivity implements ILoginView {

    private EditText mEtUsername;
    private EditText mEtPassword;
    private Button mBtnLogin;

    private LoginPresenter mLoginPrinter = new LoginPresenter(this);

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

        findViews();
    }

    private void findViews() {
        mEtUsername = (EditText) findViewById(R.id.editText2);
        mEtPassword = (EditText) findViewById(R.id.editText);
        mBtnLogin = (Button) findViewById(R.id.button);
        mBtnLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mLoginPrinter.login(getUserName(), getPassword());
                showLoading();
            }
        });
    }

    public String getUserName() {
        return mEtUsername.getText().toString();
    }

    public String getPassword() {
        return mEtPassword.getText().toString();
    }

    public void showLoading() {
        Toast.makeText(this, "开始转菊花", Toast.LENGTH_SHORT).show();
    }

    public void hideLoading() {
        Toast.makeText(this, "结束转菊花", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void toSuccessPage(UserBean userBean) {
        hideLoading();
        Toast.makeText(this, userBean.getUsername() + "跳转去主页面", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showErrMessage(String message) {
        hideLoading();
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
    }
}

Presenter:同时持有View和Model,关心交互部分,完全无关逻辑。持有Model和View

package com.example.mvpdemo.presenter;

import com.example.mvpdemo.bean.UserBean;

/**
 * 登录Presenter接口,处理交互
 */
public interface ILoginPresenter {
    void login(String name,String password);
    void loginSuccess(UserBean user);
    void loginFail(String errMsg);
}
package com.example.mvpdemo.presenter;

import com.example.mvpdemo.bean.UserBean;
import com.example.mvpdemo.model.IUserBiz;
import com.example.mvpdemo.model.UserBiz;
import com.example.mvpdemo.view.ILoginView;

/**
 * Presenter层,同时持有View和Model,只关心交互,不涉及双方逻辑
 */
public class LoginPresenter implements ILoginPresenter {
    private IUserBiz mUserBiz;
    private ILoginView mLoginView;

    public LoginPresenter(ILoginView mLoginView) {
        this.mLoginView = mLoginView;
        this.mUserBiz = new UserBiz(this);
    }

    @Override
    public void login(String name, String password) {
        mUserBiz.login(name, password);
    }

    @Override
    public void loginSuccess(UserBean user) {
        mLoginView.toSuccessPage(user);
    }

    @Override
    public void loginFail(String errMsg) {
        mLoginView.showErrMessage(errMsg);
    }
}

如上。MVP之外的所有东西都不包含,实现简单的分层。

Google 官推MVP架构 Presenter层将Model的逻辑也处理在一起,不仅仅作为中间交互层

相关文章: