MVP架构实例讲解-登录界面
MVP优缺点就不介绍了,主要说下应用,今天已程序登录的界面讲解如何用MVP架构,写的不好的地方欢迎指正
在介绍之前,先看下demo的目录结构
-
定义网络相关接口
网络请求都是共通的,所以可以把网络部分单独摘出来。
首先定义网络请求状态接口。所有的网络请求都包括开始,成功,不成功。所以网络请求状态接口如下所示
public interface RequestStatus<T> {
void onStart();
void onSuccess(T t);
void onError();
}
使用泛型的原因是返回结果类型不确定。
其次是定义网络请求的方法接口
public interface NetTask<T> {
/**
*
* @param t 请求参数类型不确定
* @param requestStatus 网络请求状态回调
*/
void exec(T t,RequestStatus requestStatus);
}
exec()方法里面传入了RequestStatus接口,是为了当网络请求有结果后回调给LoginPreserter用的。
-
定义LoginActivity 和LoginPresenter需要实现的接口。
咱们分析下,登录的时候有那些状态。涉及网络请求,为了友好的交互,肯定有显示dialog和隐藏dialog,还有就是登录验证成功和失败。
1.定义LoginActivity需要实现的接口LoginViewInterface
2.定义LoginPresenter需要实现的接口LoginPresenterInterface,这个接口用于LoginActivity和LoginPresenter的交互。
public class LoginBaseInterface {
public interface LoginPresenterInterface<T>{
void requestToLogin(T t);
}
public interface LoginViewInterface<T>{
void showRequestNetDialog();//展示请求网络的dialog
void cancelRequestNetDialog();//finish掉dialog
void LoginSuccess(T t);//登录成功
void LoginUnSuccess();//登录不成功
}
}
如代码所示,我将这两个接口写到一个LoginBaseInterface类中了,方便管理。
- Model层处理
因为将的是MVP,所以先说model层吧,在说这个之前先建一个实体类LoginBean,用于存储用户名和密码,因为在网络请求的时候需要用到这两个参数。
model层主要用于请求网络获取数据。所以实现之前定义的网络请求的接口NetTask
请求网络的逻辑都在这里实现。
public class LoginModel implements NetTask<LoginBean> {
@Override
public void exec(LoginBean loginBean, RequestStatus requestStatus) {
String name = loginBean.getUserName();
String pwd = loginBean.getUserPwd();
if (name == null && TextUtils.isEmpty(name)) {
requestStatus.onError();
return;
}
if (pwd == null && TextUtils.isEmpty(pwd)) {
requestStatus.onError();
return;
}
//这里处理和网络交互的逻辑
requestStatus.onStart();
//模拟请求网络
if (!name.equals("18888888888")) {
requestStatus.onError();
return;
} else {
if (!pwd.equals("123456")) {
requestStatus.onError();
return;
} else {
requestStatus.onSuccess("恭喜你登录成功");
}
}
}
}
- View层处理(LoginActivity)
1.实现LoginBaseInterface中的LoginViewInterface并重载里面的方法。
2.得到网络请求的对象,将它和自己传给LoginPresenter以得到LoginPresenter对象。
3.点击登录按钮的时候。调用LoginPresenter里面的方法。
LoginActivity的所有代码
package com.mvptest.mvp_demo.login;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.mvptest.mvp_demo.R;
public class LoginActivity extends AppCompatActivity implements LoginBaseInterface.LoginViewInterface, View.OnClickListener {
private ProgressBar mLoginPb;
/**
* 手机号
*/
private EditText mUserMobileEt;
/**
* 密码
*/
private EditText mUserPwdEt;
/**
* 登 录
*/
private TextView mLoginConfirmTv;
private LoginPresenter loginPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
initView();
LoginModel loginModel = new LoginModel();
loginPresenter = new LoginPresenter(loginModel,this);
}
@Override
public void showRequestNetDialog() {
if (!mLoginPb.isShown()) {
mLoginPb.setVisibility(View.VISIBLE);
}
}
@Override
public void cancelRequestNetDialog() {
if (mLoginPb.isShown()) {
mLoginPb.setVisibility(View.INVISIBLE);
}
}
@Override
public void LoginSuccess(Object o) {
if (mLoginPb.isShown()) {
mLoginPb.setVisibility(View.INVISIBLE);
}
Toast.makeText(getApplicationContext(), (String)o, Toast.LENGTH_LONG).show();
}
@Override
public void LoginUnSuccess() {
if (mLoginPb.isShown()) {
mLoginPb.setVisibility(View.INVISIBLE);
}
Toast.makeText(getApplicationContext(), "登录失败", Toast.LENGTH_LONG).show();
}
private void initView() {
mLoginPb = (ProgressBar) findViewById(R.id.login_pb);
mUserMobileEt = (EditText) findViewById(R.id.user_mobile_et);
mUserPwdEt = (EditText) findViewById(R.id.user_pwd_et);
mLoginConfirmTv = (TextView) findViewById(R.id.login_confirm_tv);
mLoginConfirmTv.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
default:
break;
case R.id.login_confirm_tv:
loginPresenter.requestToLogin(new LoginBean(mUserMobileEt.getText().toString().trim(),mUserPwdEt.getText().toString().trim()));
break;
}
}
}
- Presenter层处理。
1.实现LoginBaseInterface.LoginPresenterInterface接口和网络请求状态接口RequestStatus
2.创建构造方法(参数含有网络请求对象和LoginBaseInterface.LoginViewInterface接口)
3.在请求网络的地方调用网络请求对象中的方法
4.将网络请求结果回调给view
package com.mvptest.mvp_demo.login;
import com.mvptest.mvp_demo.netWork.NetTask;
import com.mvptest.mvp_demo.netWork.RequestStatus;
/**
* Author:wang_sir
* Time:2018/5/7 20:48
* Description:This is LoginPresenter
* LoginPresenter 实现约定接口中的presenter接口和请求网络状态的接口
*/
public class LoginPresenter implements LoginBaseInterface.LoginPresenterInterface<LoginBean>,RequestStatus<String> {
private NetTask<LoginBean> netTask;
private LoginBaseInterface.LoginViewInterface viewInterface;
public LoginPresenter(NetTask<LoginBean> netTask, LoginBaseInterface.LoginViewInterface viewInterface) {
this.netTask = netTask;
this.viewInterface = viewInterface;
}
@Override
public void requestToLogin(LoginBean loginBean) {
netTask.exec(loginBean,this);
}
@Override
public void onStart() {
viewInterface.showRequestNetDialog();
}
@Override
public void onSuccess(String str) {
viewInterface.cancelRequestNetDialog();
viewInterface.LoginSuccess(str);
}
@Override
public void onError() {
viewInterface.cancelRequestNetDialog();
viewInterface.LoginUnSuccess();
}
}
- 归总下整个流程。
view层。
1.进入到LoginActivity后,先得到网络请求逻辑处理类的对象LoginModel.
2.得到LoginPresenter对象。
3.点击登录按钮的时候。view告诉presenter,你帮我请求下网络(调用LoginPresenter中请求网络的方法。)
presenter层
4.LoginPresenter告诉LoginModel启用请求网络的方法。(在LoginPresenter中请求网络的方法里调用网络请求逻辑处理类LoginModel去请求网络。)
5.LoginModel将请求结果回调给LoginPresenter,LoginPresenter通知view更改。
整个MVP的使用就讲完了,不懂的小伙伴最好自己动手实现一下。不懂的地方可以留言,有问题的地方欢迎指正。
完整代码已提交GitHub。地址:https://github.com/DevelopWb/MVP_DEMO.git
上一篇: Android中的MVP架构