1.咱们这里谈mvp开发模式咱们就直说mvp开发模式,关于它和其它开发模式的区别咱们这边就不累述了,下面进入正题。
2.首先咱们需要知道什么mvp,为什么要使用它?
MVP:model+view+presenter, 一针见血的说就是:view的事件抽象成接口,model用于处理去网络请求、数据操作,presenter用来充当中间件把model中的数据传递到view接口中,或者可以这样理解:把用户想做的事情传递到p中,在p中在把用户想做的事情传递到m中,在m中处理完这件事情在回到p中,回到p中后再从p中传递到v中,这就是一个完整的循环,通过什么来实现呢?接口。
3.长话短说,我以大部分人最容易立即的方式来把当前mvp分解组合使用,下面来看具体代码实现。
4.以登录为例子:
大家看到这个图片后,首先咱们来分析一下它怎么来使用mvp开发模式,
1.咱们先来分析一下,当用户点击登录后会先判断用户名和密码,然后再去请求服务器接口,然后为了友好会有一个加载框,请求完毕后要取消当前加载框,成功后要有一系列的处理,失败要给用户提示。这是完整的流程。
2.那么mvp的v要怎么定义呢:
public interface LoginViewCallback{
//用于显示加载框
void showDialog();
//用于取消加载框
void dismissDialog();
//用于提示用户失败信息
void failedToast(String msg);
//用户接收服务器成功消息 (复杂数据请在model中处理后再返回)
void success(String result);
}
咱们这个view接口就定义好了,当然这只是最基本的,大家有需要可以自行在接口中增加函数。
3.咱们定义完v以后开始定义p:
接口:
public interface LoginPresenter{
//定义登录的接口(大家别吐槽 我这里只是模拟一下登录过程)
void requestLogin(String username,String password);
//(下面两个怎么和上面的重复了呢? 这个你们自行改,我只是模式一下过程,别打我。。。)
//用于提示用户失败信息
void failedToast(String msg);
//用户接收服务器成功消息 (复杂数据请在model中处理后再返回)
void success(String result);
}
实现:需要把v的接口注册进来,并且初始化m
public class LoginPresenterImpl implements LoginPresenter{
private LoginModel model;
private LoginViewCallback viewCallback;
public LoginPresenterImpl(LoginViewCallback viewCallback){
//初始化viewCallback
this.viewCallback = viewCallback;
//初始化Modell
this.model =new LoginModelImpl(this);
}
@Override
public void requestLogin(String username,String password) {
if(viewCallback!=null){
//通知Activity显示加载框
viewCallback.showDialog();
}
if(model!=null){
//告诉model开始执行
model.requestLogin(username,password);
}
}
@Override
public void failedToast(String errorContent) {
if(viewCallback!=null){
//通知Activity取消加载框并做失败后的处理
viewCallback.dismissDialog();
viewCallback.failedToast(errorContent);
}
}
//
@Override
public void successs(String result) {
if(viewCallback!=null){
//通知Activity取消加载框、并做成功后的处理。。。。
viewCallback.dismissDialog();
viewCallback.successs(result);
}
}
}
4.定义完v和p现在只剩下m了:
接口:
public interface LoginModel{
//定义登录的接口(是不是和上面p的接口差不多呀,后面再实际开发中你们可以优化,暂时这样写方便理解。。。)
void requestLogin(String username,String password);
}
实现:
public class LoginModelImpl implements LoginModel {
private static final intFAILED =0;
private static final intSUCCESS =1;
privateLoginPresenter presenter;
privateHandler handler =newHandler() {
@Override
public voidhandleMessage(Message msg) {
switch(msg.what) {
case FAILED:
//这里非空判断一下 然后在通知p
presenter.failed(msg.obj.toString());
break;
case SUCCESS:
//这里非空判断一下 然后在通知p
presenter.successs(msg.obj.toString());
break;
}
}
};
public LoginModelImpl(LoginPresenter presenter) {
this.presenter = presenter;
}
@Override
public voidrequestLogin(finalString username, finalString password) {
//模拟一下登录过程
handler.postDelayed(new Runnable() {
@Override
public void run() {
if(username.equals("admin")&&password.equals("123456")){
handler.sendEmptyMessage(SUCCESS);
}else {
handler.sendEmptyMessage(FAILED);
}
}
},2000);
}
}
5.下面来看一下Activity的实现,没写注释 。。。
public class LoginActivity extends Activity implements LoginViewCallback {
private LoginPresenterpresenter;
private ProgressDialog progressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_activity);
presenter=new LoginPresenterImpl(this);
progressDialog =new ProgressDialog(this);
}
public void request(View view){
//登陆
presenter.requestLogin(((EditText)findViewById(R.id.et_username)).getText().toString(),((EditText)findViewById(R.id.et_pwd)).getText().toString());
}
@Override
public void showDialog() {
if(null!=progressDialog&&!progressDialog.isShowing()){
progressDialog.show();
}
}
@Override
public voiddismissDialog() {
if(null!=progressDialog&&progressDialog.isShowing()){
progressDialog.dismiss();
}
}
@Override
public void failedToast(String errorContent) {
Toast.makeText(this,errorContent,Toast.LENGTH_SHORT).show();
}
@Override
public void successs(String result) {
Toast.makeText(this,result,Toast.LENGTH_SHORT).show();
}
}
到这里就写完了,但是有个问题,这样写内存会泄漏,怎么处理呢?大家想一下什么样的情况下内存才会泄漏,是不是有别的类持有了当前Activity的实例导致Activity不能被系统回收旧会发生内存泄漏呢,大家只要加个方法在onDestroy方法中把持有Activity实例的对象置空就可以了,大家琢磨一下,有疑惑的可以在下方留言或者加本人的联系方式来交流。