我这里不多说什么是MVP,重点说怎么写MVP;
说明: MVP和MVC的最大区别:MVP中M和V之间没有直接的联系;V和P之间也是通过接口联系的。
先看看他的目录结构:在这里可以看见model、presenter、view三个包。
然后看看里面的详细目录:
好了下面开始创建我们的类了:
- 1、首先看看view层
我们模仿登录,界面很简单,有两个EditText和一个button。
view层有两个东西,一个是Activity,一个是View的接口;Activity还是之前的Activity但是里面的所有业务逻辑都是抽成方法,放到了View的接口中。
分析一下有哪些业务逻辑呢?就是有哪些功能:
1)获取EditText上的文字,及获取用户名和密码;
2)点击Button的时候弹出加载动画,登录成功后取消加载动画;
3)点击button时改变button的状态,如改变文字等;
所以我们View层的接口就搞定了
/**
* Created by ws on 17/8/4.
* View层的接口,主要是界面的显示,和用户的良好交互
*
* 分析:1、点击button的时候要显示Progress,加载之后隐藏progress
* 2、点击button后改变button的文字状态,颜色等,这里只实现了文字,其他的根据需求定义哈
* 3、可以获取用户名和密码
*
* 对应的Activity要实现这个接口,因为所有的View都在Activity上进行的初始化
*/
public interface LoginViewInterface {
void showProgress();
void hindProgress();
void changeButtonText(String btn_text);
String getUsername();
String getPassword();
}
然后说说我们的Activity,Activity一定要实现View的接口,要不啥也干不了,Activity中的动作都写在了接口中,但是具体的实现还是在Activity中实现的,还有Activity的另一个作用就是初始化,初始化那些View。
view要与presenter又关系,但是又不能直接实现presenter的接口,这样还会造成在view中操作model,所以只能持有presenter的接口的实现类的引用,从而可以保证在presenter中既操作了view又操作了model
public class LoginActivity extends AppCompatActivity implements LoginViewInterface {
private EditText mUserNameEdit;
private EditText mPasswordEdit;
private Button mLoginBtn;
private LinearLayout mLoadingLinear;
private ContentLoadingProgressBar mLoadingPregress;
private LoginMVPim loginMVPim;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
initViews();
initListeners();
}
private void initViews() {
mUserNameEdit = (EditText) findViewById(R.id.a_login_edit_username);
mPasswordEdit = (EditText) findViewById(R.id.a_login_edit_password);
mLoginBtn = (Button) findViewById(R.id.a_login_btn_login);
mLoadingLinear = (LinearLayout) findViewById(R.id.a_login_linear_progress);
mLoadingPregress = (ContentLoadingProgressBar) findViewById(R.id.a_login_pg_progress);
//持有presenter的引用(通过presenter来操作model)
loginMVPim = new LoginMVPim(this);
}
private void initListeners() {
mLoginBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loginMVPim.loginMV();
}
});
}
@Override
public void showProgress() {
mLoadingLinear.setVisibility(View.VISIBLE);
mLoadingPregress.show();
}
@Override
public void hindProgress() {
mLoadingLinear.setVisibility(View.GONE);
mLoadingPregress.hide();
}
@Override
public void changeButtonText(String btn_text) {
mLoginBtn.setText(btn_text);
}
@Override
public String getUsername() {
return mUserNameEdit.getText().toString();
}
@Override
public String getPassword() {
return mPasswordEdit.getText().toString();
}
}
- 2、接下来看看model层
先说个最简单的实体类,和正常的没区别
public class User {
private String username;
private String password;
public User(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
view层是处理界面的,model是处理数据的,view层的接口实现了一些可以改变界面的东西,那model层的接口就是改变数据了,我们的例子中什么时候会操作数据呢,只有在登录的时候,会涉及到数据,所以model层的接口中的方法就确定了。
public interface UserModelInterface {
//登录的时候我们要知道用户名和密码,同时还要知道登录的结果,所以就给了个接口用来回调。
void login(String username, String password, LoginCallBack callBack);
}
注意:
这个回调在presenter层,因为它给Model层回调,更改View层的状态,确保 Model层不直接操作View层。
疑问
这里可能会有疑问,为什么model层的接口和presenter层的接口都有实现的类,而view层的直接由Activity实现了呢?
因为view层的接口都是操作View的,这些View又都是在Activity中初始化的,自然而然就由Activity实现了。
public class UserModelInterfaceIm implements UserModelInterface {
@Override
public void login(String username, String password, LoginCallBack callBack) {
//只是模拟,具体的自己修改
if ("15811470222".equals(username) && "123456".equals(password)){
callBack.loginSuccess("成功啦");
User user = new User(username,password);
}else {
callBack.loginError("失败啦");
}
}
}
- 3、view层和model层都准备好了,看看presenter怎么联系他俩吧
还是先把刚刚说的那个回调的接口展示给大家吧
public interface LoginCallBack {
void loginSuccess(String data);
void loginError(String error);
}
控制view和model的presenter接口
public interface LoginMVP {
void loginMV();
}
重点喽,我门看看到底是怎么操作View和model的
要记得同时也要实现回调的接口,要不操作了没有任何的反应,那就白弄了。
public class LoginMVPim implements LoginMVP ,LoginCallBack{
private LoginViewInterface viewInterface;
private UserModelInterfaceIm userModelInterfaceIm;
//操作view和model就要有着两个的对象,看清楚哈一个是接口,一个是接口的实现类
public LoginMVPim(LoginViewInterface viewInterface) {
this.viewInterface = viewInterface;
userModelInterfaceIm = new UserModelInterfaceIm();
}
@Override
public void loginMV() {
viewInterface.showProgress();
viewInterface.changeButtonText("已经点击");
userModelInterfaceIm.login(viewInterface.getUsername(),viewInterface.getPassword(),this);
}
@Override
public void loginSuccess(String data) {
viewInterface.hindProgress();
Log.e("------------>","data"+data);
}
@Override
public void loginError(String error) {
viewInterface.hindProgress();
Log.e("---------->","error"+error);
}
}
大概就是这样了,还是要自己一点点的去领悟
我的理解和学习过程
参考文章:
Android中的MVP模式,带实例