The MVP connection

The simple explanation is that M-> Module processes data, V->Act displays the interface, and P->M and V communicate through channels, that is, P is used to connect data and interface together. In this way, interface and data can be completely independent. Act only deals with things related to interface, Module only deals with data, and P is only responsible for communication between the two to achieve decoupling.

Simply implement an MVP without any encapsulation

For the login screen, for example, the files required are roughly the following





image.png

ILoginView LoginPresenter needs a way to interact with LoginAct. For example, the presenter needs to get the name of the login box through the ACT, and act needs the code returned by the presenter after processing the login data

public interface ILoginView {
    String getUserName();
    String getUserPwd();
    void onSuccess(String code);
}Copy the code

IRequestLoginLoginPresenter needs and loginmodules interactive method, such as presenter need to log in as a result, obtained through the module The Module needs presenter to pass it username and PWD and an instantiated interface to call back and forth

public interface IRequestLogin {
    void toLogin(String userName, String pwd, IRequestResult requestResult);
}Copy the code

IRequestResultLoginPresenter need real-time obtaining loginmodules returns the result

public interface IRequestResult {

    void onSuccess(String result);

    void onFailed(String result);

}Copy the code

With the three pipes defined, you can implement the three MVP themes module, View, and Presenter

LoginAct implements the ILoginView interface and holds the present object for LoginPresenter to interact with it. As you can see, there is no place for the act to process data. All it needs to do is provide the name and password for the presenter to log in via the present. The code returned by presenter is also received.

public class LoginAct extends AppCompatActivity implements ILoginView { private static final String TAG = "LoginAct"; LoginPresenter loginPresenter = new LoginPresenter(); @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); loginPresenter.tologin(this); } @Override public String getUserName() { return "userName"; } @Override public String getUserPwd() { return "userPwd"; } @Override public void onSuccess(String code) { Log.e(TAG, code); }}Copy the code

The LoginModule is only used for data processing, such as requesting a code from the presenter’s name and PWD and returning it to the presenter through the interface

public class LoginModule implements IRequestLogin{ @Override public void toLogin(String name, String pwd, IRequestResult requestResult) { requestResult.onSuccess("success->"+name+" "+pwd); }}Copy the code

LoginPresenter acts as a bridge between the two. It has two objects, one module and one view. So you can see that it’s middleware that operates on modules and views so that they can be linked together. When act initiates a login, He gets the name and PWD from the View and asks the server to get the return values from the Module, which he passes to act.

public class LoginPresenter implements IRequestResult {
    private LoginModule loginModule;
    private ILoginView loginView;

    public void tologin(LoginAct loginAct) {
        loginView = loginAct;
        loginModule = new LoginModule();
        loginModule.toLogin(loginView.getUserName(), loginView.getUserName(), this);
    }

    @Override
    public void onSuccess(String result) {
        loginView.onSuccess(result);
    }

    @Override
    public void onFailed(String result) {

    }

}Copy the code

After a simple implementation, encapsulate Base





image.png

See 3 ports missing. Put them in BaseContract files. Come up with a name for your contract. Don’t be so serious. BaseContract does not have any common elements, so leave a base in case you need it later. The IBaseModule is used to implement common features in all data processing, such as all modules requesting data to return a string

public class BaseContract { public interface IBaseModule { } public interface IBasePresenter { } public interface IBaseView { void showToast(String msg); }}Copy the code

BaseAct is used to encapsulate properties common to acts. For example, all acts implement an IBaseView interface and hold a Presenter object, instantiate presenter in onCreate, and instantiate the Module and View in Presenter

public abstract class BaseAct<V extends BaseContract.IBaseView,P extends BasePresenter> extends AppCompatActivity implements BaseContract.IBaseView {

    public P presenter;

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

        if (presenter != null) {
            presenter.attatchWindow(initModule(),this);
        }

        initView();

    }

    protected abstract void initView();

    protected abstract P initPresenter();

    protected abstract BaseModule initModule();

    @Override
    protected void onDestroy() {
        super.onDestroy();
        presenter.detachWindow();
    }
}Copy the code

BaseModule does nothing

public class BaseModule implements BaseContract.IBaseModule {
}Copy the code

BasePresenter holds both module and View and is released on actdeStory

public class BasePresenter<M extends BaseModule, V extends BaseContract.IBaseView> { public M module; public V view; void attatchWindow(M m, V v) { this.module = m; this.view = v; } void detachWindow() { this.module = null; this.view = null; }}Copy the code

Use Act after Base

The LoginContract, as before, defines the data to interact with

public class LoginContract { interface ILoginView extends BaseContract.IBaseView { String getName(); String getPwd(); void onLoginResult(String code); } public interface ILoginPresenter extends BaseContract.IBasePresenter { void getResult(LoginBean bean); } public interface ILoginModule extends BaseContract.IBaseModule { void toLogin(String name, String pwd, ILoginPresenter iLoginPresenter); }}Copy the code

LoginAct eliminates the step of initializing presenter

public class LoginAct extends BaseAct<LoginContext.ILoginView, LoginPresenter> implements LoginContext.ILoginView { private static final String TAG = "LoginAct"; @Override public void showToast(String msg) { } @Override protected void onResume() { super.onResume(); presenter.toLogin(); } @Override protected BaseModule initModule() { return new LoginModule(); } @Override protected void initView() { } @Override protected LoginPresenter initPresenter() { return new LoginPresenter(); } @Override public String getName() { return "name"; } @Override public String getPwd() { return "pwd"; } @Override public void onLoginResult(String code) { Log.e(TAG, code); }}Copy the code

The LoginModule requests the data and returns the result, with little difference

public class LoginModule extends BaseModule implements LoginContract.ILoginModule { @Override public void toLogin(String Name, String PWD, LoginContract ILoginPresenter ILoginPresenter) {/ / network operation, the data returned LoginBean LoginBean = new LoginBean (); loginBean.setCode(name + pwd); iLoginPresenter.getResult(loginBean); }}Copy the code

LoginPresenter dispenses with instantiating the Module and View

public class LoginPresenter extends BasePresenter<LoginModule, LoginAct> implements LoginContract.ILoginPresenter { public void toLogin() { module.toLogin(view.getName(), view.getPwd(), this); } @Override public void getResult(LoginBean bean) { view.onLoginResult(bean.getCode()); }}Copy the code

So here’s a simple process from implementation to encapsulation of an MVP… But there is still a long way to go.