MVC-MVP

2018-11-27  本文已影响0人  吃茶泡饭丶

任何架构的设计目的都是为了:低耦合,高复用,易测试,好维护。

MVC

MVC(Model View Controller),是软件架构中最常见的一种框架,简单来说就是通过Controller的控制去操作Model的数据,并返回给View展示。


MVC.png

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

setContentView的作用???

在Android中MVC并不完美,View既依赖于Controller又依赖于Model,View同时含有Controller与Model的引用;UI逻辑同时存在于View与Model之间导致业务逻辑与UI逻辑无法分离,在修改UI逻辑时, 也需要修改Model, 降低了架构的灵活性,增加模块耦合, 影响重构。

MVP

MVP作为MVC的演化,解除了View和Module的耦合,同时又带来了良好的可扩展性,可测试性。对于Android来说,MVP的Model层相对于MVC是一样的,而activity/fragment不再是Controller层,而是纯粹的view层,所有关于用户事件的转发全部交由Presenter层处理。
MVP与MVC最大的区别在于Model与View之间的交互由Presenter完成而Presenter与View之间的交互是通过接口的方式。
Google官方相关MVP样例
来自官网的架构图

mvp.png
图中除了Activity/Fragment的黄色部分外都算是Model数据层,REPOSITORY是用来管理数据存储的,Remote data source和Local data source分别代表远程(网络)和本地(SQL)的数据来源。

以登录为例
按照MVP的思路:
这里我创建了一个CallBack,在Callback中定义数据请求的各种反馈状态,方便Model层向Presenter层反馈请求信息。

/**
 * @Author: chichapaofan
 * @CreateDate: 2018/11/1
 * @Description: 请求结果
 */
public interface CallBack {

    /**
     * 请求成功
     *
     * @param date
     */
    void onSuccess(String date);

    /**
     * 请求成功,无法正常返回数据
     *
     * @param msg
     */
    void onFailure(String msg);

    /**
     * 请求数据失败
     */
    void onError();

    /**
     * 请求结束,无论成功失败
     */
    void onFinish();
}

Model
在Model类中进行具体的网络请求操作。通过判断请求的参数反馈不同的请求状态。

/**
 * @Author: chichapaofan
 * @CreateDate: 2018/11/1
 * @Description: Model层
 */
public class LoginModel {

    /**
     * 获取数据
     *
     * @param param
     * @param callBack
     */
    public static void getData(final String param, final CallBack callBack) {
        //模拟网络请求
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                if (param.equals("normal")) {
                    callBack.onSuccess("参数:" + param + "/请求结果:网络数据成功");
                } else if (param.equals("failure")) {
                    callBack.onFailure("参数:" + param + "/请求结果:参数有误");
                } else if (param.equals("error")) {
                    callBack.onError();
                }
                callBack.onFinish();
            }
        }, 3000);
    }
}

View
View接口的作用是根据具体业务的需要,为Presenter提供调用Activity中具体UI逻辑操作的方法。

/**
 * @Author: chichapaofan
 * @CreateDate: 2018/11/1
 * @Description:View层
 */
public interface LoginView {

    /**
     * 显示正在加载进度框
     */
    void showLoading();

    /**
     * 隐藏正在加载进度框
     */
    void hideLoading();

    /**
     * 请求成功展示数据
     */
    void showData(String data);

    /**
     * 展示失败信息
     */
    void showFailureMessage(String msg);

    /**
     * 数据请求异常调用此接口
     */
    void showError();
}

Presenter
Presenter类是具体的逻辑业务处理类,负责请求数据,处理数据请求的反馈。
为了能够通过View接口通知Activity进行更新界面等操作,需要在Presenter类的构造方法中传递一个View接口的参数。

/**
 * @Author: chichapaofan
 * @CreateDate: 2018/11/1
 * @Description:Persenter层
 */
public class LoginPresenter {

    private LoginView loginView;

    public LoginPresenter(LoginView loginView) {
        this.loginView = loginView;
    }

    public void getData(String param) {
        //展示加载
        loginView.showLoading();
        LoginModel.getData(param, new CallBack() {
            @Override
            public void onSuccess(String date) {
                loginView.showData(date);
            }

            @Override
            public void onFailure(String msg) {
                loginView.showFailureMessage(msg);
            }

            @Override
            public void onError() {
                loginView.showError();
            }

            @Override
            public void onFinish() {
                loginView.hideLoading();
            }
        });
    }
}

在Activity中
在Activity代码中如果想要调用Presenter就要先实现Presenter需要的View接口。

public class LoginActivity extends AppCompatActivity implements LoginView {

    private LoginPresenter loginPresenter;

    private AutoCompleteTextView mEmailView;
    private EditText mPasswordView;
    private View mProgressView;
    private View mLoginFormView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login2);
        mEmailView = findViewById(R.id.email);
        mPasswordView = findViewById(R.id.password);
        mProgressView = findViewById(R.id.login_progress);
        mLoginFormView = findViewById(R.id.email_sign_in_button);
        
        //
        loginPresenter=new LoginPresenter(this);

        mLoginFormView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //
                if(mEmailView.getText().toString().equals("normal")){
                    loginPresenter.getData("normal");
                }else if(mEmailView.getText().toString().equals("failure")){
                    loginPresenter.getData("failure");
                }else if(mEmailView.getText().toString().equals("error")){
                    loginPresenter.getData("error");
                }
            }
        });
    }

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

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

    @Override
    public void showData(String data) {
        Toast.makeText(this, data, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showFailureMessage(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showError() {
        Toast.makeText(this, "服务器开小差惹", Toast.LENGTH_SHORT).show();
    }
}

到此简单的MVP架构实现完成!!

上一篇下一篇

猜你喜欢

热点阅读