您的位置:首页 > 移动开发 > Android开发

android MVP 开发模式

2016-04-14 18:55 495 查看


android MVP 开发模式的理解
       在进入MVP介绍前。我们先来看一下一直沿用的MVC的开发的模式。

       明人一看上面的结构图就知道MVC中是允许Model 和 View  进行交互的。

每种模式都有利与弊,不能说那种模式好与不好。为了“高内聚,低耦合”的思想。个人觉得MVP更能体现之特性。

下面让我们来看看MVP的结构图:


   View对应于activity,负责View的绘制以及用户的交互,理应做到View是最薄的一层,利于UI重新设计与变更。
     Model 数据源与实体模型。比如,保存到本地的数据。数据库的数据。网络请求回来的数据。
     Presenter 负责View与Model的交互。起到一个中间的角色。说白了就是个控制器。由它来控UI的数据来源和UI显示。


如果理解这三个概念。接下来就说说代码结构吧。

代码分块。这并不是MVP的主旨。可以根据个人爱好来分。最重要的是我们在写代码时,如何运用MVP的思维。做到代码清淅明了,维护性高。逻辑简单明了。

接下来看一个简单的例子。如

/**
* Created by cc on 16/4/13.
*/
public interface ILoginView {

String getPhone();

String getPassWord();

void setPhone(String phone);

void setPassWroid(String passWroid);

void startIndexActivity();

void startForgetActivity();

Context getContext();

void promptToastMessge(String msg);

void showProgressBar(String msg);

void setProgressBarMessage(String msg);

void hideProgressBar();

}


/**
* Created by cc on 16/4/13.
*/
public interface ILoginMode {

void onSuccess(Object object);

void onFail(Object object);
}

/**
* Created by cc on 16/4/13.
*/
public class LoginService {

public LoginService(final ILoginMode iLoginMode) {

//这里模拟网络请求。按道理来说。这里不该出现os包的代码。这里只为了测试。
// 建设 model层。放在异步线程执行。可以试一下
//Rx(rxjava或rxandroid) 与 Retrogit
//Rx(rxjava或rxandroid) 可以简单理解为"异步"
//Retrogit网络请求

new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//模拟加载数据

if (new Random().nextBoolean()){
iLoginMode.onSuccess("请求成功");
return;
}
iLoginMode.onFail("请求失败");
}
},3000);

}
}


/**
* Created by cc on 16/4/13.
*/
public class LoginPresenter {

private ILoginView mILoginView;

public LoginPresenter(ILoginView iLoginView) {
mILoginView = iLoginView;
}

public void onCreate() {

LocalLoginPhone localLoginPhone = new LocalLoginPhone();

String phone = localLoginPhone.getLoginPhone(mILoginView.getContext());

mILoginView.setPhone(phone);

}

public void deletePhoneClick() {

mILoginView.setPhone("");

}

public void deletePassWordClick() {
mILoginView.setPassWroid("");
}

public void forgetPassWordClick() {
mILoginView.startForgetActivity();
}

public void LoginClick() {

String phone = mILoginView.getPhone();

if (TextUtils.isEmpty(phone)) {

mILoginView.promptToastMessge("填写信息有误");

return;
}

String possWord = mILoginView.getPassWord();

if (TextUtils.isEmpty(possWord)) {

mILoginView.promptToastMessge("填写信息有误");

return;
}

mILoginView.showProgressBar("正在加载");

LoginService loginService = new LoginService(new ILoginMode() {
@Override
public void onSuccess(Object object) {
mILoginView.setProgressBarMessage(object.toString());
mILoginView.hideProgressBar();

mILoginView.startIndexActivity();
}

@Override
public void onFail(Object object) {
mILoginView.setProgressBarMessage(object.toString());
mILoginView.hideProgressBar();
mILoginView.promptToastMessge("提交失败");
}
});

}

}


/**
* Created by cc on 16/4/13.
*/
public class LogInActivity extends BaseActivity implements ILoginView {

private EditText login_et_phone, login_et_password;

private Button login_btn_delete_phone, login_btn_delete_password, login_btn_login, login_btn_forget_password;

private LoginPresenter mLoginPresenter;

private LittleDialog mDialog;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.act_login);

initView();

mLoginPresenter = new LoginPresenter(this);
mLoginPresenter.onCreate();
}

private void initView() {

login_et_phone = (EditText) findViewById(R.id.login_et_phone);
login_et_password = (EditText) findViewById(R.id.login_et_password);
login_btn_delete_phone = (Button) findViewById(R.id.login_btn_delete_phone);
login_btn_delete_password = (Button) findViewById(R.id.login_btn_delete_password);
login_btn_login = (Button) findViewById(R.id.login_btn_login);
login_btn_forget_password = (Button) findViewById(R.id.login_btn_forget_password);

login_btn_delete_phone.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mLoginPresenter.deletePhoneClick();
}
});
login_btn_delete_password.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mLoginPresenter.deletePassWordClick();
}
});
login_btn_login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mLoginPresenter.LoginClick();
}
});
login_btn_forget_password.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mLoginPresenter.forgetPassWordClick();
}
});

}

@Override
public String getPhone() {
return login_et_phone.getText().toString().trim();
}

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

@Override
public void setPhone(String phone) {

login_et_phone.setText(phone);

}

@Override
public void setPassWroid(String passWroid) {
login_et_password.setText(passWroid);
}

@Override
public void startIndexActivity() {
UIHelper.startActivity(this, IndexActivity.class, null);
}

@Override
public void startForgetActivity() {

}

@Override
public Context getContext() {
return this;
}

@Override
public void promptToastMessge(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}

@Override
public void showProgressBar(String msg) {
mDialog = new LittleDialog(this, msg);
mDialog.show();

}

@Override
public void setProgressBarMessage(String msg) {
if (null != mDialog)
mDialog.setMessage(msg);
}

@Override
public void hideProgressBar() {

if (null != mDialog)
mDialog.dismiss();

}

}


/**
* UI操作辅助类
* @author alafighting 2016-0
*/
public class UIHelper {

/**
* 界面跳转
* @param context
* @param activity
* @param bundle
*/
public static void startActivity(Context context, Class<? extends Activity> activity, Bundle  bundle) {
if (context == null) {
throw new NullPointerException("context不能为空");
}
Intent intent = new Intent(context, activity);

if (null !=bundle){
intent.putExtras(bundle);
}

context.startActivity(intent);
}

/**
* 打开主界面
* @param context
*/
public static void startMain(Context context) {
startActivity(context, IndexActivity.class,null);
}

}


/**
* Created by cc on 16/4/13.
*/
public class BaseActivity extends AppCompatActivity {

public Context getContext() {
return super.getApplicationContext();
}

public Activity getActivity() {
return this;
}

public <T extends android.support.v4.app.Fragment> T findSupportFragment(Class<T> fragmentClass) {
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
android.support.v4.app.Fragment fragment = fragmentManager.findFragmentByTag(fragmentClass.getName());
return (T) fragment;
}

public <T extends android.support.v4.app.Fragment> T newSupportFragment(Class<T> fragmentClass, Bundle args) {
android.support.v4.app.Fragment fragment = android.support.v4.app.Fragment.instantiate(getContext(), fragmentClass.getName(), args);
fragment.setArguments(args);
return (T) fragment;
}
}


上面的例子是不是看起来很明了。关键问题,大家看到这代码后,会认为这只是把逻辑代码模块的东西放到一另一个类而已。如果你这么理解。说明你对写代码的一个整体认识观不是很有艺术。人人都说写代码是一门艺术。

上面的代码结构还是有好处的。如,当测试跟你说这接口请求出错了。出bug了。这时平常我们会去找到这个接口在那个activity里调用。在那一行代码里。聪明的人可能不会这么干。或许习惯自已写测试用例时,只需调用LoginService实现ILoginModel接口就好了,就可以知道自已有没有搞错了。是不是很 66666

最后说一个mvp 的优点

MVP的优点:

模型与视图完全分离,我们可以修改视图而不影响模型

可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter内部

我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非    常的有用,因为视图的变化总是比模型的变化频繁。

如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑(单    元测试)

说明。上面有一两张图是截网上的。如果有侵权,请及时联系我删除,谢谢。

在此感谢以上几个人。老八,壳,替补,roy,朽木,在我理解MVP 过程中。他们给予我解答
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android mvp 开发模式