MVP模式的个人理解

MVP模式 个人短浅的理解

最近项目没有很紧(虽然我项目一直不紧),于是看了一下一些mvp模式的博客,现在此记录下自己的观点,仅供参考。当然,如果有兄弟或者姐妹能指出我理解中的误区和偏差,更是不胜感激,下面开始。

传统MVC模式中的项目,都是Activity既承载了View的刷新,又要进行Controller的处理,这样就会造成在大部分的Activity中代码十分的庞大,给后期的后期的维护造成极大的负荷;而且,最最可恶的是,会让人分不清到底MVC模式到底是什么鬼,尤其是像我这种半吊子码农,养成堆砌代码的坏习惯。下面来拨开个传统的项目的栗子(被用烂了的登录功能呗):

public class LoginActivity extends BaseActivity {
private Button button;
private EditText loginNameEt;
private EditText pwdEt;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.main);
    initView();
    addEvent();
}

@Override
public void initView() {
    button = (Button) findViewById(R.id.click);
    loginNameEt = (EditText) findViewById(R.id.login_name);
    pwdEt = (EditText) findViewById(R.id.login_pwd);
}

@Override
public void addEvent() {
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            doLogin(loginNameEt.getText().toString(), pwdEt.getText().toString());
        }
    });
}

//这里是Controller的工作吖,为什么会放在View里呢?okey,为了写起来方便
private void doLogin(String name, String pwd) {
//登录处理
//…
}

@Override
public void getExa() {

}

}
然后我们来看这个代码,毫无疑问,这么看起来还算蛮干净整洁的,但是仔细想想,这还是在堆代码吖,从刚从代码界入行我就这么写,到现在还在这么写,这对我在代码界的狗生没有丝毫的帮助,,,那么该怎么办呢???
话不说多先上图(原谅我这么多年一直做一只凶猛的盗图狗)
这里写图片描述
根据这个图来解释下MVP模式:所谓的mvp,即是(model-处理业务逻辑(主要是数据读写,或者与后台通信(其实也是读写数据)),view-处理ui控件,presenter-主导器,操作model和view),当然这是官方的说法;我的理解是presenter作为一个中间件来处理我们需要做的操作,并通知view更新及model的修改
那让我们变成“gua牛”一步一步来往深爬。所谓知其然必得知其所以然,然后我们来分析:
假设我们有一个Activity(这里就不说model嘞,仿照view的处理),想通过这个Activity来实现登录功能。嗯,View的刷新应该包括:登录后页面的跳转或者当前页面的数据的清除;Controller应该做的事包括:登录的处理。
首先我们来定义present,我们先来定义一个接口,根据上面分析可知,这个接口需要实现登录功能:

public interface LoginPresenter {

    void doLogin(String name, String pwd);
}

然后再来定义一个View的接口,毕竟如果想通过present来控制view,必须有个view的引用传进来,不然我还控制个毛吖

public interface LoginView {
    void onClearText();

    void onLoginResult(boolean result, int code);
}

好啦,指定了view的接口,在activity实现了这个接口,就可以对View进行处理嘞。
根据View和present的接口,我们来实现我们的present类,

public class LoginPresenterCompl implements LoginPresenter {
    LoginView loginView;
    User user;

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

    @Override
    public void doLogin(String name, String pwd) {
        //网络请求或者其他操作
        //...
        //选一个做处理.如有必要写在回调中,还要注意是否需要通过主线程来刷新View
        loginView.onLoginResult(true, 200);
        loginView.onClearText();
    }
}

那为什么这么写呢,正如上面所说,当我想要控制view,必须通过一个实例引用来控制我view的刷新,所以定义了一个以view为参数的构造方法,然后就是在dologin(x,y)中进行我们的Controllor的处理及通知view刷新嘞。
下面提供Activity的实现,

//实现了LoginView 接口,在我看来其实是通过回调来实现view的刷新(说这话感觉好虚啊,求重喷)
public class LoginActivity extends BaseActivity implements LoginView {
    private Button button;
    private EditText loginNameEt;
    private EditText pwdEt;
    private LoginPresenter loginPresenter;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.main);
        //new 一个LoginPresenterCompl实例,并将activity本身作为View传递给present来进行页面更新
        loginPresenter = new LoginPresenterCompl(this);
        initView();
        addEvent();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void initView() {
        button = (Button) findViewById(R.id.click);
        loginNameEt = (EditText) findViewById(R.id.login_name);
        pwdEt = (EditText) findViewById(R.id.login_pwd);
    }

    @Override
    public void addEvent() {
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                                loginPresenter.doLogin(loginNameEt.getText().toString().trim(), pwdEt.getText().toString().trim());

            }
        });
    }

    @Override
    public void getExa() {

    }

    @Override
    public void onClearText() {
        loginNameEt.setText("");
        pwdEt.setText("");
    }

    @Override
    public void onLoginResult(boolean result, int code) {
        Toast.makeText(MyActivity.this, "the result is " + result + "  the code is " + code, Toast.LENGTH_SHORT).show();
                Intent intent = new Intent();
                intent.setClass(MyActivity.this, SecondActivity.class);
                startActivity(intent);
    }
}

忽然感觉没什么好说的了,就是在onclick的时候调用present进行login处理,然后login处理后调用传入的view进行回调来进行页面的刷新。
最后上一个我的项目结构图:
目录结构图
由于并没有在实际项目中使用过,所以觉得如果是这么实现的话,代码的逻辑及模块是能清晰好多,但是是不是耦合性增大了呢,还请碰巧看到的大牛们不吝赐教。

相关内容推荐