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.