Android MVP模式中,单个Activity/Fragment如何对应多个VP

Android MVP模式中,单个Activity/Fragment如何对应多个VP

写在前面

貌似现在的主流已经是MVVM模式了,但是作为Android小白,还是决定从MVP开始学习。

通常情况下,或者说作为一个还不算坏的设计,一个Activity/Fragment应该对应一个业务(一套MVP接口及实现)。但是往往由于种种原因,很难保证Activity/Fragment不会对应多个业务。没准明天产品经理(对于程序员来说这属于不可抗力)就会告诉你,他们打算把登录和注册放在一个Fragment上。

通常的MVP封装

通常我们在使用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上。说完就飘飘然的离去。

通过代理模式化N为1

我们可不可以巧妙的把多个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

你可能感兴趣的:(Android)