深入解析MVP怎么玩,接口抽取深入解析
MVP 全称:Model-View-Presenter ;MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。
MVC和MVP的区别?
作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会直接从Model中读取数据而不是通过 Controller。具体怎么写呢?具体请看注释,没提出说明
我们需要写个ViewInterface,ModelInterface以及管理这这两个接口的Presenter类
1、ViewInterface这个是必须的:里面主要定义一些操作界面的方法、结果反馈的方法、UI隐藏的方法,具体方法按照需求划分抽取,主要由activity实现。
2、ModelInterface不是必须的如果业务单一就不需要,如果处理业务需要多个model每一个model都要实现这个公共接口,便于在Presenter中回调,主要由model层实现。
3、Presenter是最重要的是一个普通类,里面定义了一下常量和标志,声明了ViewInterface,ModelInterface两个接口和一个public内部回调接口CallBack。CallBacK主要以匿名接口在Presenter中实现,在实现的方法中可以用ViewInterface回调具体实现的activity的方法。
具体代码如下所示:
ViewInterface代码:
该接口负责定义对view层的所有操作。例如UI更新、view界面数据获取,网络请求成功信息展示、以及界面跳转等各种UI操作。主要供Presenter回调来修改界面,达到控制者的作用,具体方法参数视具体情况而定。
/**
* 该接口负责定义对view层的所有操作。例如UI更新、view界面数据获取,网络请求成功信息展示、
* 以及界面跳转等各种UI操作。主要供Presenter回调来修改界面,达到控制者的作用,具体方法参
* 数视具体情况而定。
*/
public interface LoginViewInterface {
//获取用户名
String getUserName();
//获取密码
String getUserPassword();
//展示失败的信息
void showLoginFailed(String error);
//展示成功的信息
void showLoginSuccess(String succ);
//成功后跳转界面
void goActivity();
//展示进度条
void showProgressBar();
//取消进度条
void dismissProgressBar();
//成功时更新页面
void updateSuccessUI();
//失败时更新页面
void updateFailedUI();
}
activity代码:通过在实现的方法中直接操作界面控件或者获取控件数据,在此就不做实现,主要必须继承ViewInterface
public class Login2Activity extends Activity implements LoginViewInterface {
@Override
public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
super.onCreate(savedInstanceState, persistentState);
ButterKnife.inject(this);
}
@Override
public String getUserName() {
return null;
}
@Override
public String getUserPassword() {
return null;
}
@Override
public void showLoginFailed(String error) {
}
@Override
public void showLoginSuccess(String succ) {
}
@Override
public void goActivity() {
}
@Override
public void showProgressBar() {
}
@Override
public void dismissProgressBar() {
}
@Override
public void updateSuccessUI() {
}
@Override
public void updateFailedUI() {
}
}
Presenter代码:
内部接口主要是供model层回调,该接口以匿名接口的方式传到model层model回调,里面主要定义一些model对UI界面操作的接口和处理结果的回调,这样能避免大量new对象造成的内存浪费。当然不仅仅可以定义这些方法可以根据需求增加和减少相关方法,将所有业务交给model层,这样就成了真正的MVP模式,如果将业务处理写在Presenter里面,将不是真正的MVP, 一般情况下接口中和view层接口一一对应,当然也可以一个callback对应多个view接口方法。
public class LoginPresernter {
private final LoginViewInterface viewInterface;
private final LoginModelInterface modelInterface;
private static LoginPresernter mPresernter;
public static boolean isSuccess=true;
private LoginPresernter(LoginViewInterface viewInterface){
this.viewInterface = viewInterface;
this.modelInterface = new UserLogin();
}
public static LoginPresernter getInstance(LoginViewInterface viewInterface){
if (mPresernter==null){
mPresernter = new LoginPresernter(viewInterface);
}
return mPresernter;
}
public void userLogin(){
String userName = viewInterface.getUserName();
String userPassword = viewInterface.getUserPassword();
modelInterface.login(userName, userPassword, new CallBack() {
/**
* 通过在匿名接口中回调实现修改实现了VIEW层定义接口的view界面
* @param string
*/
@Override
public void onSuccess(String string) {
viewInterface.showLoginSuccess(string);
viewInterface.goActivity();//登录成功的回调
//当然可以跳转多个界面,不同界面通过做标志判断这样VIEW层业务处理将会极少
}
@Override
public void onFailed(Throwable throwable) {
viewInterface.showLoginFailed(throwable.getMessage());//登录失败的回调
}
@Override
public void updateUi(Boolean isSuccess) {
if (isSuccess==LoginPresernter.isSuccess){
viewInterface.updateSuccessUI();//更新页面
}else{
viewInterface.updateFailedUI();//更新页面
}
}
@Override
public void showProgress() {
viewInterface.showProgressBar();//展示进度条的回调
}
@Override
public void dismissProrgress() {
viewInterface.dismissProgressBar();//取消进度条的回调的
}
@Override
public void goActivity() {
viewInterface.goActivity();
}
});
}
/**
* 内部接口主要是供model层回调,该接口以匿名接口的方式传到model层供model回调,里面
* 主要定义一些model对UI界面操作的接口和处理结果的回调,这样能避免大量new对象造成的
* 内存浪费。当然不仅仅可以定义这些方法可以根据需求增加和减少相关方法,将所有业务交给
* model层,这样就成了真正的MVP模式,如果将业务处理写在Presenter里面,将不是真正的MVP,
* 一般情况下接口中和view层接口一一对应,当然也可以一个callback对应多个view接口方法。
*/
public interface CallBack{
//成功的回调
void onSuccess(String string);
//失败的回调
void onFailed(Throwable throwable);
//修改界面的
void updateUi(Boolean isSuccess);
//展示进度条
void showProgress();
//取消进度条
void dismissProrgress();
//界面跳转
void goActivity();
}
}
ModeInterface代码:
值得注意的是必须要有Presenter中接口,主要供方法回调,只有一个实现类可以不提供接口,但可读性差,建议都有接口
public interface LoginModelInterface {
/**
* 值得注意的是必须要有Presenter中接口,主要供方法回调,只有一个实现类可以不提供接口,但可读性差,建议都有接口
* @param userName
* @param userPassword
* @param callBack
*/
void login(String userName, String userPassword, LoginPresernter.CallBack callBack);
}
model实现类代码:在model中通过callBack对象将结果返回或者修改界面,
通过Presenter内部接口回调UI方法
public class UserLogin implements LoginModelInterface {
/** 标识客户端当前是否为后台登录 */
private boolean mIfBackgroundLogin = true;
/** 与引擎交互的类 */
private SysClient mClient = new SysClient();
/** 记录登录账号的变量 */
private String mAccount = "";
/** 记录登录密码的变量 */
private String mPassword = "";
@Override
public void login(String userName, String userPassword, LoginPresernter.CallBack callBack) {
if (TextUtils.isEmpty(userName.trim())){
callBack.onFailed(new Throwable("登录账号不能为空!"));
return;
}
if (TextUtils.isEmpty(userPassword.trim())){
callBack.onFailed(new Throwable("登录密码不能为空!"));
return;
}
mAccount=userName;
mPassword=userPassword;//这里的数据是从Presenter获得的
doUserAuth(callBack);
}
/**
* 用户登录认证
*/
private void doUserAuth(LoginPresernter.CallBack callBack) {
if (!NetworkHelper.isConnected(UIUtils.getContext())) {
callBack.onFailed(new Throwable("請打開網絡"));
return;
} else {
userAuth("",callBack);
}
}
private void userAuth(final String param, final LoginPresernter.CallBack callBack) {
try {
RequestParams params = null;
String service = "";
if (TextUtils.isEmpty(param)) {
params = mClient.userAuthParam(mAccount, mPassword);
service = Login.SERVICE;
} else {
callBack.onFailed(new Throwable("不支持這種方式登錄哦"));
return;
}
AsyncHttpclient.post(service, params, new TextHttpResponseHandler() {
@Override
public void onStart() {
callBack.showProgress();//通过Presenter回调UI方法
}
@Override
public void onFailure(int i, Header[] headers, String s, Throwable throwable) {
callBack.dismissProrgress();
callBack.onFailed(new Throwable("用戶名或密碼錯誤"));
}
@Override
public void onSuccess(int i, Header[] headers, String s) {
callBack.dismissProrgress();
callBack.onSuccess("登录成功");
callBack.goActivity();
}
},true);
}catch (Exception e){
}
}
}
这样就一个完美的MVP搭建成功了,至于接口中的方法需要开发者通过需求划分大小,不用太细能满足需求即可。你也可以将业务全部写在Presenter中,这样callBack中就能写一写方法。如果不知道接口里面方法该有那些,请看注释
这是我个人对MVP的一些理解和改进,如果有不对的地方希望高手帮我指出,谢谢。有不懂的也可以评论交流额。