Android 学习之MVP模式

由于前段时间面试,发现大多数公司开始问MVP模式,你会不会这种框架牧师,那时候表示不会,所以现在来恶补一下。

首先:什么是MVP模式?说一下我的理解。

M(Model层):在android中主要是处理数据的存在。比如你界面有一个按钮需要请求网络校验数据,那么校验数据的这步就应该放在Model层。

V(View层):这个就很好理解了,界面相关的东西都在View层,比如Activity,Fragment,adapter。界面层主要提供与人的交互,比如我该怎么显示,失败与成功各要显示什么,与用户提供什么样的交互。

P(Presenter层):这个相当于逻辑处理层。处理View想干的事情。比如说点击这个按钮你想去登录,那么就调用doLogin方法。想去下载图片就去调用doDownLoad方法。这一层主要是要去干什么,而不是怎么干。


然后:我们为什么要使用这种模式。

使用这种模式之前我们的开发模式都是MV模式的。把View 和 Presenter放在一起。比如我们有一个activity用于登录:LoginActivity,它的作用是收集用户输入的用户名和密码然后去Net校验。

以前我们写这种功能也很好实现。2个EditText分别输入用户名和密码,1个Button处理数据提交,写一个login方法传入edittext获取的用户名密码访问网络。一切的一切全写在Activity中了。这样写的好处是什么,简单的项目我们很快就能完成。此时如果我们有一个activity,它上面布满了各种控件,各种需要处理的事件。我们想象一下这个activity中要有多少个方法,有多少行代码,这样会造成可读性很差。这时候MVP就出现了。。。它相当于把一个activity处理数据界面展示等分成了3个部分。提高了代码的可读性。现如今大型项目几乎都已经开始使用这种模式了。


最后:我们来看一个简单的例子。

Android 学习之MVP模式

先来看一下这个目录结构model主要用于存储数据相关,View主要用于存储UI相关 ,presenter主要用于储存行为相关。


View层代码:

ILoginView接口


package com.example.myapplication.login.view;


public interface ILoginView {
    public String getUserName();
    public String getPassWord();
    public void showProgressBar();
    public void hideProgressBar();
    public void showSuccMsg();
    public void showErrorMsg();
}
MAinActivity.java

package com.example.myapplication.login.view;

import android.support.v7.app.AppCompatActivity;
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.example.myapplication.R;
import com.example.myapplication.login.presenter.IPresenter;
import com.example.myapplication.login.presenter.LoginPresents;

import butterknife.BindView;
import butterknife.ButterKnife;

public class MainActivity extends AppCompatActivity implements ILoginView{
    @BindView(R.id.editUser)
    public EditText userName;
    @BindView(R.id.editPass)
    public EditText userPass;
    @BindView(R.id.login)
    public Button login;
    @BindView(R.id.progressbar)
    public ProgressBar mProgressBar;
    private LoginPresents loginPresents;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        ButterKnife.bind(this);
        loginPresents=new LoginPresents(this);
        login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loginPresents.doLogin();
            }
        });
    }

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

    @Override
    public String getPassWord() {
        return userPass.getText().toString();
    }

    @Override
    public void showProgressBar() {
        mProgressBar.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideProgressBar() {
        mProgressBar.setVisibility(View.GONE);
    }

    @Override
    public void showSuccMsg() {
        Toast.makeText(MainActivity.this,"login succ",Toast.LENGTH_LONG).show();
    }

    @Override
    public void showErrorMsg() {
        Toast.makeText(MainActivity.this,"login fail",Toast.LENGTH_SHORT).show();
    }
}

Model层代码:

Userbean.java

package com.example.myapplication.login.model;


public class UserBean {
    public String userName;
    public String userPassWord;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserPassWord() {
        return userPassWord;
    }

    public void setUserPassWord(String userPassWord) {
        this.userPassWord = userPassWord;
    }
}
ILoginModel接口

package com.example.myapplication.login.model;


public interface ILoginModel {
    public void checkUser(String user ,String pass,CallBack callBack);
    interface CallBack{
        void Success();
        void Fail();
    }
}
LgoinModel.java

package com.example.myapplication.login.model;

import java.util.logging.Handler;


public class LoginModel implements ILoginModel {
	//模拟网络请求
    @Override
    public void checkUser(String user, String pass, final CallBack callBack) {
        new android.os.Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                callBack.Success();
            }
        }, 3000);
    }
}
Presenter层代码:

Ipresenter接口

package com.example.myapplication.login.presenter;

import com.example.myapplication.login.view.ILoginView;

public interface IPresenter {
    public void doLogin();
}
LoginPresenter.java

package com.example.myapplication.login.presenter;

import com.example.myapplication.login.model.ILoginModel;
import com.example.myapplication.login.model.LoginModel;
import com.example.myapplication.login.view.ILoginView;



public class LoginPresents implements IPresenter {
    private ILoginView loginView;
    private LoginModel loginModel;
    public LoginPresents(ILoginView view){
        loginView=view;
        loginModel=new LoginModel();
    }
    @Override
    public void doLogin() {
        loginView.showProgressBar();
        loginModel.checkUser(loginView.getUserName(), loginView.getPassWord(), new ILoginModel.CallBack() {
            @Override
            public void Success() {
                loginView.hideProgressBar();
                loginView.showSuccMsg();
            }

            @Override
            public void Fail() {
                loginView.hideProgressBar();
                loginView.showErrorMsg();
            }
        });
    }
}

所有代码就是这些。MVP层一定会有3个接口,ILoginModel,ILoginView,IPresenter。

它们之间的逻辑是MainActivty中的按钮点击调用了行为层(presenter)的LoginPresenter去实现登录功能,LoginPresenter去调用数据层(Model)的LoginModel执行网络处理操作得到返回数据,然后再传递给View层(MainActivity.java)。

对于MVP我想说的是越难的项目感觉代码看起来越清晰,但是简单的项目还是不要用了。会多写很多代码。。。。。