在《MVP架构设计模式1》中,着重介绍过MVP架构设计,以及可能会出现内存泄漏的优化,那么在本节中,将会深入企业,看企业级的MVP架构是如何完成 的。
1、BaseActivity
在MVP架构中,Activity已经属于View层,不再是MVC中的C层,因此Activity主要就是负责加载View,或者向P层请求获取数据。
public abstract class BaseActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayout());
initView();
initData();
initListener();
}
//初始化监听
protected abstract void initListener();
//初始化数据
protected abstract void initData();
//初始化View,findViewById...
protected abstract void initView();
protected abstract int getLayout();
}
2、BaseModel
在MVP架构中,Model层主要负责网络请求或者数据库等操作,而且之和P层有直接的关系,因此在使用Model时只能是BasePresenter的实现类使用。
public abstract class BaseModel<P extends BasePresenter> {
public P mPresenter;
public BaseModel(P mPresenter){
this.mPresenter = mPresenter;
}
}
3、BasePresenter
在MVP架构中,P层属于建立Model层和View层的桥梁,既要获取View层的引用,又要与Model层建立连接回调数据,还要防止内存泄漏的情况发生。
public abstract class BasePresenter<V extends BaseActivity,M extends BaseModel> {
//获取View的引用
private V mView;
//获取Model层的引用
private M mModel;
public BasePresenter(){
this.mModel = getModelInstance();
}
//子类实例化,获取特定的Model
protected abstract M getModelInstance();
//绑定View
public void attachView(V mView){
this.mView = mView;
}
//解绑View
public void detachView(V mView){
if(this.mView != null){
this.mView = null;
}
}
}
3部分完成之后,需要完善BaseActivity。
public abstract class BaseActivity<P extends BasePresenter> extends AppCompatActivity implements View.OnClickListener {
protected P mPresenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayout());
initView();
initData();
initListener();
//初始化P层
mPresenter = createPresenter();
//绑定当前View
mPresenter.attachView(this);
}
protected abstract P createPresenter();
//初始化监听
protected abstract void initListener();
//初始化数据
protected abstract void initData();
//初始化View,findViewById...
protected abstract void initView();
protected abstract int getLayout();
@Override
protected void onDestroy() {
super.onDestroy();
mPresenter.detachView(this);
}
}
4、MVP架构的使用
设计一个登陆功能,需要输入用户名和密码,点击按钮登录,做回调。
在做回调的时候,使用契约合同,面向接口编程。
public interface ILoginContract {
public interface M{
void requestLogin(String username,String password) throws Exception;
}
interface VP{
void requestLogin(String username,String password);
void responseLoginResult(boolean status);
}
}
(1)LoginActivity
登录界面需要持有LoginPresenter
的引用,并且实现契约合同中的VP接口发起请求和回调;在点击登录按钮的时候,调用requestLogin
方法,此时就是去向P层请求获取数据。
public class LoginActivity extends BaseActivity<LoginPresenter> implements ILoginContract.VP {
private EditText et_username,et_password;
private Button btn_login;
private TextView tv_login;
@Override
protected LoginPresenter createPresenter() {
return new LoginPresenter();
}
@Override
protected void initListener() {
btn_login.setOnClickListener(this);
}
@Override
protected void initData() {
}
@Override
protected void initView() {
et_username = findViewById(R.id.et_username);
et_password = findViewById(R.id.et_password);
btn_login = findViewById(R.id.btn_login);
tv_login = findViewById(R.id.tv_login);
}
@Override
protected int getLayout() {
return R.layout.activity_login;
}
@Override
public void onClick(View v) {
String username = et_username.getText().toString();
String password = et_password.getText().toString();
//请求登录
requestLogin(username,password);
}
@Override
public void requestLogin(String username, String password) {
//向P层请求数据
mPresenter.requestLogin(username,password);
}
@Override
public void responseLoginResult(boolean status) {
//接受回调
if(status){
tv_login.setText("已登录成功");
}
}
}
(2)LoginPresenter
当View层发起请求的时候,P层需要向Model层请求获取数据,在这里就需要做部分业务逻辑,判断输入的信息的合法性。
public class LoginPresenter extends BasePresenter<LoginActivity,LoginModel> implements ILoginContract.VP{
@Override
protected LoginModel getModelInstance() {
return new LoginModel(this);
}
@Override
public void requestLogin(String username, String password) {
//向Model层请求获取数据
//.....校验信息完整性
try {
mModel.requestLogin(username,password);
} catch (Exception e) {
e.printStackTrace();
//异常处理,保存到日志
}
}
@Override
public void responseLoginResult(boolean status) {
//向View层回调
mView.responseLoginResult(status);
}
}
(3)LoginModel
在Model层中,真正执行requestLogin
发起网络请求,将请求得到的数据,通过responseLoginResult
回调接口返回P层。
public class LoginModel extends BaseModel<LoginPresenter> implements ILoginContract.M{
public LoginModel(LoginPresenter mPresenter) {
super(mPresenter);
}
@Override
public void requestLogin(String username, String password) throws Exception {
//网络请求返回数据
mPresenter.responseLoginResult(true);
}
}
在P层中,持有了View层的引用,因此将数据返回View层,View层接收到数据后,更新UI界面。
5、MVP架构的升级
(1)在之前使用契约合同的时候,需要自己手写并主动实现,那么在这里就可以做一个升级,开发者不需要主动去实现接口。
面向接口编程,就是父类告诉子类,让子类干什么,也就是说,在父类中传入一个接口,让子类去实现实例化接口,实现其中的方法。
public abstract class SuperBase<CONTRACT> {
//获取特定的契约合同
public abstract CONTRACT getContract();
}
在Base层,需要传入这个接口,这是强制的,而不需要开发者主动去implements
接口。
Model层:
public abstract class BaseModel<P extends BasePresenter,CONTRACT> extends SuperBase<CONTRACT> {
public P mPresenter;
public BaseModel(P mPresenter){
this.mPresenter = mPresenter;
}
}
Presenter层:
public abstract class BasePresenter<V extends BaseActivity,M extends BaseModel,CONTRACT> extends SuperBase<CONTRACT> {
//获取View的引用
protected V mView;
//获取Model层的引用
protected M mModel;
public BasePresenter(){
this.mModel = getModelInstance();
}
//获取特定的Model
protected abstract M getModelInstance();
//绑定View
public void attachView(V mView){
this.mView = mView;
}
//解绑View
public void detachView(V mView){
if(this.mView != null){
this.mView = null;
}
}
}
View层:
public abstract class BaseActivity<P extends BasePresenter,CONTRACT> extends AppCompatActivity implements View.OnClickListener {
protected P mPresenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayout());
initView();
initData();
initListener();
//初始化P层
mPresenter = createPresenter();
//绑定当前View
mPresenter.attachView(this);
}
//契约接口
protected abstract CONTRACT getContract();
protected abstract P createPresenter();
//初始化监听
protected abstract void initListener();
//初始化数据
protected abstract void initData();
//初始化View,findViewById...
protected abstract void initView();
protected abstract int getLayout();
@Override
protected void onDestroy() {
super.onDestroy();
mPresenter.detachView(this);
}
}
在使用的时候,就可以面向接口编程。
在View层可以通过Presenter
层的getContract
获取接口,进行方法调用和回调
@Override
protected ILoginContract.VP getContract() {
return new ILoginContract.VP() {
@Override
public void requestLogin(String username, String password) {
//P层同样需要面向接口
mPresenter.getContract().requestLogin(username,password);
}
@Override
public void responseLoginResult(boolean status) {
if(status) {
tv_login.setText("登录成功");
}
}
};
}
相较于之前的MVP架构设计,这是一种全新的架构设计思路,采用了面向接口编程,扩展性更高,耦合度降低。
6、Fragment的MVP架构设计
其实Fragment和Activity在MVP中,都属于View层,形式差不多,只是加载View的时候些许不同,Fragment的主要职责就是显示View。
View层:
public abstract class BaseFragment<P extends BaseFragmentPresenter,CONTRACT> extends Fragment implements View.OnClickListener {
//p层
protected P mPresenter;
View rootView;
//创建接口
protected abstract CONTRACT getContract();
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
mPresenter = createPresenter();
mPresenter.attachView(this);
}
protected abstract P createPresenter();
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
if(rootView == null) {
rootView = LayoutInflater.from(getContext())
.inflate(getLayout(), container, false);
}
initView(rootView);
initListener();
return rootView;
}
protected abstract void initListener();
protected abstract void initView(View rootView);
protected abstract int getLayout();
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initData();
}
protected void initData() {
}
@Override
public void onDetach() {
super.onDetach();
if(mPresenter != null){
mPresenter.detachView(this);
}
}
}
Presenter层:
public abstract class BaseFragmentPresenter<V extends BaseFragment,M extends BaseFragmentModel,CONTRACT> extends SuperBase<CONTRACT> {
protected V mFragment;
protected M mModel;
public BaseFragmentPresenter(){
this.mModel = getModelInstance();
}
protected abstract M getModelInstance();
//绑定View
public void attachView(V mFragment){
this.mFragment = mFragment;
}
//解绑View
public void detachView(V mFragment){
if(mFragment != null){
this.mFragment = null;
}
}
}
Model层:
public abstract class BaseFragmentModel<P extends BaseFragmentPresenter,CONTRACT> extends SuperBase<CONTRACT> {
protected P mPresenter;
public BaseFragmentModel(P mPresenter){
this.mPresenter = mPresenter;
}
}