貌似现在的主流已经是MVVM模式了,但是作为Android小白,还是决定从MVP开始学习。
通常情况下,或者说作为一个还不算坏的设计,一个Activity/Fragment应该对应一个业务(一套MVP接口及实现)。但是往往由于种种原因,很难保证Activity/Fragment不会对应多个业务。没准明天产品经理(对于程序员来说这属于不可抗力)就会告诉你,他们打算把登录和注册放在一个Fragment上。
通常我们在使用MVP模式时,都会进行一些简单的封装,尽可能的简化业务层的代码体量。(我一般叫它懒人Activity)
public abstract class LazyActivity<P extends IPresenter> extends BaseActivity {
protected P mPresenter;
protected abstract P createPresenter();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPresenter = createPresenter();
if (mPresenter == null) {
throw new NullPointerException("Presenter is null! Do you return null in createPresenter()?");
}
mPresenter.attachView(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mPresenter != null) {
mPresenter.detachView();
}
}
protected P getPresenter(){
return mPresenter;
}
}
当我们有了这样一个懒人专用的MVP Activity时,就不用为每个Activity再进行创建、绑定和解绑Presenter了。我们一直这么开心地用着。
细心的你很快发现了,我的这个懒人Activity里面,一个Activity只能对应一个Presenter。好在设计之初,我们严格遵守了1对1的关系,这让我们节省了不少力气。
不巧的是,产品经理带着老板的口谕来找你,要把登录和注册合并到一个Activity上。说完就飘飘然的离去。
我们可不可以巧妙的把多个Presenter合并起来呢?当然可以,别忘了我们曾经学过的代理模式!将两个Presenter悄悄的合并在一起,欺骗我们的懒人Activity!
首先我们创建代理接口
public class LoginRegisterContract {
public interface ILoginRegisterView extends LoginContract.ILoginView, RegisterContract.IRegisterView {
}
public interface ILoginRegisterPresenter extends LoginContract.ILoginPresenter, RegisterContract.IRegisterPresenter {
}
}
然后对之前的接口定义稍作修改,ILoginPresenter和IRegisterPresenter实现IPresenter的模板参数改为上面代理接口中的LoginRegisterContract.ILoginRegisterView。
/* 登录业务 */
public interface LoginContract {
interface ILoginView extends BaseView {
void loginSuccess(String msg);
void loginFailed(String msg);
}
//interface ILoginPresenter extends IPresenter {
interface ILoginPresenter extends IPresenter<LoginRegisterContract.ILoginRegisterView> {
void login(String name, String password);
}
}
/* 注册业务 */
public class RegisterContract {
interface IRegisterView extends BaseView {
void registerSuccess(String msg);
void registerFailed(String msg);
}
//interface IRegisterPresenter extends IPresenter{
interface IRegisterPresenter extends IPresenter<LoginRegisterContract.ILoginRegisterView>{
void register(String name, String password);
}
}
最后实现LoginRegisterContract定义的接口就OK了。
public class LoginRegisterPresenterImpl extends BasePresenter<LoginRegisterContract.ILoginRegisterView> implements LoginRegisterContract.ILoginRegisterPresenter {
RegisterContract.IRegisterPresenter mRegisterPresenter = new ...;
LoginContract.ILoginPresenter mLoginPresenter = new ...
@Override
public void register(String name, String password){
mRegisterPresenter.register(name, password);
}
@Override
public void login(String name, String password){
mLoginPresenter.login(name, password);
}
/* 绑定视图等接口也需要重写,给mRegisterPresenter和mLoginPresenter绑定视图。 */
}
public class MainActivity extends LazyActivity<LoginRegisterContract.ILoginRegisterPresenter> implements LoginRegisterContract.ILoginRegisterView {
@Override
protected LoginRegisterContract.ILoginRegisterPresenter createPresenter() {
return new LoginRegisterPresenterImpl();
}
}
其实这几天思考这个问题的过程中,看到更多的是依赖注入的方式解决“1对多”的问题,肯定比本文所述的这种方法要好的多。但是由于才疏学浅,android还未入门,对于那些方法还没理解。或许时隔半年之后,再回过头看这篇博客,也只能一笑而过。
ps.示例代码
https://github.com/sunchb/MVPDemo.git