原文出处:[高级MVP架构封装演变全过程](http://blog.csdn.net/yulong0809/article/details/78622428)
本文重点是封装一个高级MVP架构,会详细的讲解如何一步步从无到有的封装成一个高级MVP架构过程。
众所周知普通的MVP模式存在内存泄露、代码冗余、界面意外关闭后在重建数据缓存等问题,本文最终封装的成果为一一解决这些问题,而且在使用过程中尽量做到使用简单而且可扩展,当然本文也只是提供了一种封装思路而已,如果不能满足你的需求还可以自行再进行扩展。
如果你觉得你不想看整个实现思路可以直接看最后的源码,望给点个star鼓励一下
[GitHub地址:https://github.com/ljqloveyou123](https://github.com/ljqloveyou123)
文章会以5个部分来整体优化封装MVP,也是一个从无到有的过程
**一、不使用MVP的代码**
**二、最简单的MVP实现**
**三、解决MVP内存泄露**
**四、简单抽象-解决MVP代码冗余**
**五、高级抽象-使用注解、工厂模式、代理模式、策略模式整体解决代码冗余、内存泄露、Presenter生命周期以及数据存储问题**
不废话了,进入正题。
场景:假如界面有一个按钮,点击后请求数据,然后成功后将返回的数据设置到一个Textview中
**一、不使用MVP的代码,一般我们会这么写**
~~~
public class MainActivity extends AppCompatActivity {
@FieldView(R.id.tv_text)
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewFind.bind(this);
}
//按钮点击事件
public void request(View view) {
clickRequest("101010100");
}
//发起请求
public void clickRequest(final String cityId) {
//请求接口
Retrofit retrofit = new Retrofit.Builder()
//代表root地址
.baseUrl("http://www.weather.com.cn/")
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiService apiService = retrofit.create(ApiService.class);
//请求
Call<WeatherBean> weatherBeanCall = apiService.requestWeather(cityId);
weatherBeanCall.enqueue(new Callback<WeatherBean>() {
@Override
public void onResponse(Call<WeatherBean> call, Response<WeatherBean> response) {
//请求成功
textView.setText(response.body().getWeatherinfo().toString());
}
@Override
public void onFailure(Call<WeatherBean> call, Throwable t) {
//请求失败
}
});
}
}
~~~
上面的代码是最原始的写法,下面我们使用最简单的MVP模式来改造这个代码。
**二、最简单的MVP实现**
思路如下:
1、首先我们先定义一个接口,用来规定针对这个界面逻辑View需要作出的动作的接口。
2、让Activity实现这个接口中的方法,也就是V层
3、创建一个类,用来封装之前的网络请求过程,也就是M层
4、再创建一个类,用来处理M层和V层之间的通信,也就是P层
下面来实现一下:
1、首先我们先定义一个接口,用来规定针对这个界面逻辑View需要作出的动作的接口。
~~~
/**
* @author 刘镓旗
* @date 2017/11/16
* @description V层接口,定义V层需要作出的动作的接口
*/
public interface RequestView1 {
//请求时展示加载
void requestLoading();
//请求成功
void resultSuccess(WeatherBean result);
//请求失败
void resultFailure(String result);
}
~~~
2、让Activity实现这个接口中的方法,也就是V层
~~~
/**
* 第二步:对应demo1
* 2,最简单的mvp模式,
* 1.Activity需要实现v层接口
* 2.Persenter需要持有v层引用和m层引用
* 3.在实现类view中创建persenter
*
*/
public class MainActivity extends AppCompatActivity implements RequestView1 {
@FieldView(R.id.tv_text)
private TextView textView;
private RequestPresenter1 presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewFind.bind(this);
//创建Presenter
presenter = new RequestPresenter1(this);
}
//点击事件
public void request(View view) {
presenter.clickRequest("101010100");
}
//请求时加载
@Override
public void requestLoading() {
textView.setText("请求中,请稍后...");
}
//请求成功
@Override
public void resultSuccess(WeatherBean result) {
//成功
textView.setText(result.getWeatherinfo().toString());
}
//请求失败
@Override
public void resultFailure(String result) {
//失败
textView.setText(result);
}
}
~~~
3、创建一个类,用来封装之前的网络请求过程,也就是M层
~~~
/**
* @author 刘镓旗
* @date 2017/11/16
* @description M层 数据层
*/
public class RequestMode1 {
private static final String BASE_URL = "http://www.weather.com.cn/";
//http://www.weather.com.cn/data/cityinfo/101010100.html
public void request(String detailId, Callback<WeatherBean> callback){
//请求接口
Retrofit retrofit = new Retrofit.Builder()
//代表root地址
.baseUrl(BASE_URL)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiService apiService = retrofit.create(ApiService.class);
//请求
Call<WeatherBean> weatherBeanCall = apiService.requestWeather(detailId);
weatherBeanCall.enqueue(callback);
}
}
~~~
4、再创建一个类,用来处理M层和V层之间的通信,也就是P层
~~~
/**
* @author 刘镓旗
* @date 2017/11/16
* @description P层
* 特点:需要持有M层和V层
*/
public class RequestPresenter1 {
private final RequestView1 mRequestView;
private final RequestMode1 mRequestMode;
public RequestPresenter1(RequestView1 requestView) {
this.mRequestView = requestView;
this.mRequestMode = new RequestMode1();
}
public void clickRequest(final String cityId){
//请求时显示加载
mRequestView.requestLoading();
//模拟耗时,可以展示出loading
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mRequestMode.request(cityId, new Callback<WeatherBean>() {
@Override
public void onResponse(Call<WeatherBean> call, Response<WeatherBean> response) {
mRequestView.resultSuccess(response.body());
}
@Override
public void onFailure(Call<WeatherBean> call, Throwable t) {
mRequestView.resultFailure(Log.getStackTraceString(t));
}
});
}
},1000);
}
}
~~~
好了,上面的4步就是最基本的MVP模式的使用了,可是这样写会内存泄露,因为如果在网络请求的过程中Activity就关闭了,Presenter还持有了V层的引用,也就是MainActivity,就会内存泄露。
**三、解决MVP内存泄露**
下面就来解决这个问题,我们将P层和V层的关联抽出两个方法,一个绑定,一个解绑,在需要的时候进行绑定V层,不需要的时候进行解绑就可以了。我们只需要修改上面Presenter中的构造代码,不需要在构造中传递V层了,然后再写一个绑定和解绑的方法,最后修改Activity创建Presenter时进行绑定,在onDestroy中进行解绑。
修改后的Presenter:
~~~
/**
* @author 刘镓旗
* @date 2017/11/16
* @description
*/
public class RequestPresenter2 {
private RequestView2 mView;
private RequestMode2 mMode;
public RequestPresenter2() {
mMode = new RequestMode2();
}
public void clickRequest(final String cityId) {
if(mView != null){
mView.requestLoading();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mMode.request(cityId, new Callback<WeatherBean>() {
@Override
public void onResponse(Call<WeatherBean> call, Response<WeatherBean> response) {
if(mView != null){
mView.resultSuccess(response.body());
}
}
@Override
public void onFailure(Call<WeatherBean> call, Throwable t) {
if(mView != null){
mView.resultFailure(Log.getStackTraceString(t));
}
}
});
}
},1000);
}
}
/**
* 绑定
* @param view
*/
public void attach( RequestView2 view) {
this.mView = view;
}
/**
* 解除绑定
*/
public void detach() {
mView = null;
}
/**
* 取消网络请求
*/
public void interruptHttp(){
mMode.interruptHttp();
}
}
~~~
修改后的MainActivity:
~~~
/**
* 第三步:对应demo2
* 上面的问题:
* 1.是会内存泄露,因为persenter一直持有Activity,如果一个发了一个请求,但是网络有点慢,这个时候退出Activity,那么请求回来后还是会调用
* Activity的回调方法,这里还是因为一直持有的问题
* 2.如果已经退出了当前界面,这个请求也没有用了,这个时候我们可以断开请求
* <p>
* 解决问题:
* 1.增加绑定和解绑的方法来解决内存泄露和退出后还会回调的问题
* 2、增加断开网络连接的方法
*/
public class MainActivity extends AppCompatActivity implements RequestView2 {
@FieldView(R.id.tv_text)
private TextView textView;
private RequestPresenter2 presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewFind.bind(this);
presenter = new RequestPresenter2();
presenter.attach(this);
}
public void request(View view) {
presenter.clickRequest("101010100");
}
@Override
public void requestLoading() {
textView.setText("请求中,请稍后...");
}
@Override
public void resultSuccess(WeatherBean result) {
//成功
textView.setText(result.getWeatherinfo().toString());
}
@Override
public void resultFailure(String result) {
//失败
textView.setText(result);
}
@Override
protected void onDestroy() {
super.onDestroy();
presenter.detach();
presenter.interruptHttp();
}
}
~~~
这样我们就解决了内存泄露的问题,但是这样还是不完美,应用中肯定不可能只有一个模块,每个模块都对应着一个V层和P层,那这样的话每个Presenter中都要定义绑定和解绑的方法,而Activity中对应的也要调用这绑定和解绑的两个方法,代码冗余。
**四、简单抽象-解决MVP代码冗余**
针对这个问题我们可以抽取出一个基类的Presenter和一个基类的Activity来做这个事情,让子类不用在写这些重复的代码。但是问题又来了,**既然是基类,肯定不止有一个子类来继承基类,那么也就是说子类当中定义的View接口和需要创建的Presenter都不相同,我们肯定在基类当中不能写死吧,那就使用泛型来设计**。
**思路**:
1. 创建一个基类View,让所有View接口都必须实现,**这个View可以什么都不做只是用来约束类型**的
2. 创建一个基类的Presenter,在**类上规定View泛型**,然后**定义绑定和解绑的抽象方法**,让子类去实现,对外在提供一个获取View的方法,
让子类直接通过方法来获取View
3. 创建一个基类的Activity,**声明一个创建Presenter的抽象方法(abstract P createPresenter())**,**因为要帮子类去绑定和解绑那么就需要拿到子类的Presenter才行,但是又不能随便一个类都能绑定的,因为只有基类的Presenter中才定义了绑定和解绑的方法,所以同样的在类(基类Activity)上可以声明泛型,在方法上使用泛型来达到目的**。
4. 修改Presenter和Activity中的代码,各自继承自己的基类并去除重复代码
**实现步骤**:
1. 创建一个基类View,让所有View接口都必须实现
~~~
/**
* @author 刘镓旗
* @date 2017/11/17
* @description 所有mvpView的父接口
*/
public interface IMvpBaseView4 {
}
~~~
2. 创建一个基类的Presenter(AbstractMvpPersenter4),在**类上规定View泛型**,然后**定义绑定和解绑的方法**,**对外在提供一个获取View的方法**(getmMvpView()),让子类直接通过方法来获取View使用即可
~~~
/**
* @author 刘镓旗
* @date 2017/11/17
* @description 指定绑定的View必须继承自IMvpBaseView4
*/
public abstract class AbstractMvpPersenter4<V extends IMvpBaseView4> {
private V mMvpView;
/**
* 绑定V层
* @param view
*/
public void attachMvpView(V view){
this.mMvpView = view;
}
/**
* 解除绑定V层
*/
public void detachMvpView(){
mMvpView = null;
}
/**
* 获取V层
* @return
*/
public V getmMvpView() {
return mMvpView;
}
}
~~~
3. 创建一个基类的Activity,**声明一个创建Presenter的抽象方法(abstract P createPresenter()),因为要帮子类去绑定和解绑那么就需要拿到子类的Presenter才行,但是又不能随便一个类都能绑定的,因为只有基类的Presenter中才定义了绑定和解绑的方法,所以同样的在类(基类Activity)上可以声明泛型,在方法上使用泛型来达到目的**
~~~
/**
* @author 刘镓旗
* @date 2017/11/17
* @description MvpActivity
* 指定子类具体的View必须继承自IMvpBaseView4
* 指定子类具体的Presenter必须继承自AbstractMvpPersenter4
*/
public abstract class AbstractMvpActivity<V extends IMvpBaseView4, P extends AbstractMvpPersenter4<V>> extends AppCompatActivity implements IMvpBaseView4 {
private P presenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//创建Presenter
if (presenter == null) {
presenter = createPresenter();
}
if (presenter == null) {
throw new NullPointerException("presenter 不能为空!");
}
//绑定view
presenter.attachMvpView((V) this);
}
@Override
protected void onDestroy() {
super.onDestroy();
//解除绑定
if (presenter != null) {
presenter.detachMvpView();
}
}
/**
* 创建Presenter
* @return 子类自己需要的Presenter
*/
protected abstract P createPresenter();
/**
* 获取Presenter
* @return 返回子类创建的Presenter
*/
public P getPresenter() {
return presenter;
}
}
~~~
4. 修改Presenter和Activity中的代码,各自继承自己的基类并去除重复代码
修改后的Presenter:
~~~
/**
* @author 刘镓旗
* @date 2017/11/17
* @description P层
*/
public class RequestPresenter4 extends AbstractMvpPersenter4<RequestView4> {
private final RequestMode4 mRequestMode;
public RequestPresenter4() {
this.mRequestMode = new RequestMode4();
}
public void clickRequest(final String cityId){
//获取View
if(getmMvpView() != null){
getmMvpView().requestLoading();
}
//模拟网络延迟,可以显示出加载中
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mRequestMode.request(cityId, new Callback<WeatherBean>() {
@Override
public void onResponse(Call<WeatherBean> call, Response<WeatherBean> response) {
//判断View是否为空
if(getmMvpView() != null){
getmMvpView().resultSuccess(response.body());
}
}
@Override
public void onFailure(Call<WeatherBean> call, Throwable t) {
if(getmMvpView() != null){
getmMvpView().resultFailure(Log.getStackTraceString(t));
}
}
});
}
},1000);
}
public void interruptHttp(){
mRequestMode.interruptHttp();
}
}
~~~
修改后的Activity:
~~~
public class MainActivity extends AbstractMvpActivity<RequestView4, RequestPresenter4>
implements RequestView4 {
@FieldView(R.id.tv_text)
private TextView textView;
private RequestPresenter3 presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewFind.bind(this);
}
@Override
protected RequestPresenter4 createPresenter() {
return new RequestPresenter4();
}
//点击事件
public void request(View view) {
getPresenter().clickRequest("101010100");
}
@Override
public void requestLoading() {
textView.setText("请求中,请稍后...");
}
@Override
public void resultSuccess(WeatherBean result) {
//成功
textView.setText(result.getWeatherinfo().toString());
}
@Override
public void resultFailure(String result) {
//失败
textView.setText(result);
}
}
~~~
到这里完美了吗?没有,还可以再抽,来分析一下还有哪些不完美的地方以及如何再优化。
**五、高级抽象-使用注解、工厂模式、代理模式、策略模式整体解决代码冗余、内存泄露、Presenter生命周期以及数据存储问题**
1. **每个子类都要重写父类创建Presenter的方法,创建一个Presenter并返回,这一步我们也可以让父类帮忙干了**,怎么做呢?我们可以采用**注解的方式**,**在子类上声明一个注解并注明要创建的类型,剩下的事情就让父类去做了,但是父类得考虑如果子类不想这么干怎么办,那也还是不能写死吧,可以使用策略模式加工厂模式来实现**,我们**默认使用这种注解的工厂**,但是**如果子类不喜欢可以通过父类提供的一个方法来创建自己的工厂**。
2. **Presenter真正的创建过程,我们可以将它放到真正使用Presenter的时候再创建**,这样的话可以稍微优化一下性能问题
3. **界面有可能会意外销毁并重建**,Activity、Fragment、View都可以**在销毁的时候通过onDestroy释放一些资源并在onSaveInstanceState方法中存储一些数据然后在重建的时候恢复,但是有可能Presenter中也需要释放一些资源存储一些数据,那么上面的结构就不能满足了,我们可以给Presenter增加生命周期的方法,让Presenter和V层生命周期同步就可以做到了**
4. 第三步中我们又给Presenter加入了一些生命周期的方法,再加上Presenter的创建绑定和解绑的方法,那么**如果我们在创建一个MvpFragment基类,或者View的基类那么这么多的代码岂不是都要copy一份吗,而且看起来也很不清晰,这里**我们可以**采用代理模式**来优化一下
好了下面来实现:
1. 我们既然要**采用工厂模式才创建Presenter**,那么我们首先来创建一个**工厂接口**
~~~
/**
* @author 刘镓旗
* @date 2017/11/17
* @description Presenter工厂接口
*/
public interface PresenterMvpFactory<V extends BaseMvpView,P extends BaseMvpPresenter<V>> {
/**
* 创建Presenter的接口方法
* @return 需要创建的Presenter
*/
P createMvpPresenter();
}
~~~
2. 然后我们**需要创建一个默认使用注解创建的工厂**,那么首先要**创建一个注解**
**注解**:
~~~
/**
* @author 刘镓旗
* @date 2017/11/17
* @description 标注创建Presenter的注解
*/
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface CreatePresenter {
Class<? extends BaseMvpPresenter> value();
}
~~~
**注解工厂**:
~~~
/**
* @author 刘镓旗
* @date 2017/11/17
* @description Presenter工厂实现类
*/
public class PresenterMvpFactoryImpl<V extends BaseMvpView, P extends BaseMvpPresenter<V>>
implements PresenterMvpFactory<V, P> {
/**
* 需要创建的Presenter的类型
*/
private final Class<P> mPresenterClass;
/**
* 根据注解创建Presenter的工厂实现类
* @param viewClazz 需要创建Presenter的V层实现类
* @param <V> 当前View实现的接口类型
* @param <P> 当前要创建的Presenter类型
* @return 工厂类
*/
public static <V extends BaseMvpView, P extends BaseMvpPresenter<V>> PresenterMvpFactoryImpl<V,P> createFactory(Class<?> viewClazz){
CreatePresenter annotation = viewClazz.getAnnotation(CreatePresenter.class);
Class<P> aClass = null;
if(annotation != null){
aClass = (Class<P>) annotation.value();
}
return aClass == null ? null : new PresenterMvpFactoryImpl<V, P>(aClass);
}
private PresenterMvpFactoryImpl(Class<P> presenterClass) {
this.mPresenterClass = presenterClass;
}
@Override
public P createMvpPresenter() {
try {
return mPresenterClass.newInstance();
} catch (Exception e) {
throw new RuntimeException("Presenter创建失败!,检查是否声明了@CreatePresenter(xx.class)注解");
}
}
}
~~~
3. 我们说了**不能写死这个工厂**,那么我们**需要使用者可以自定义**,那么我们还需要给使用者提供一个设置的方法,我们**定义一个接口提供设置工厂、获取工厂、获取Presenter的方法,然后让V层来实现这个接口**,这样V层的子类就可以通过相应的方法使用了
~~~
/**
* @author 刘镓旗
* @date 2017/11/20
* @description 代理接口
*/
public interface PresenterProxyInterface<V extends BaseMvpView,P extends BaseMvpPresenter<V>> {
/**
* 设置创建Presenter的工厂
* @param presenterFactory PresenterFactory类型
*/
void setPresenterFactory(PresenterMvpFactory<V,P> presenterFactory);
/**
* 获取Presenter的工厂类
* @return 返回PresenterMvpFactory类型
*/
PresenterMvpFactory<V,P> getPresenterFactory();
/**
* 获取创建的Presenter
* @return 指定类型的Presenter
*/
P getMvpPresenter();
}
~~~
4. 给Presenter增加生命周期的方法
~~~
/**
* @author 刘镓旗
* @date 2017/11/17
* @description 所有Presenter的基类,并不强制实现这些方法,有需要在重写
*/
public class BaseMvpPresenter<V extends BaseMvpView> {
/**
* V层view
*/
private V mView;
/**
* Presenter被创建后调用
*
* @param savedState 被意外销毁后重建后的Bundle
*/
public void onCreatePersenter(@Nullable Bundle savedState) {
Log.e("perfect-mvp","P onCreatePersenter = ");
}
/**
* 绑定View
*/
public void onAttachMvpView(V mvpView) {
mView = mvpView;
Log.e("perfect-mvp","P onResume");
}
/**
* 解除绑定View
*/
public void onDetachMvpView() {
mView = null;
Log.e("perfect-mvp","P onDetachMvpView = ");
}
/**
* Presenter被销毁时调用
*/
public void onDestroyPersenter() {
Log.e("perfect-mvp","P onDestroy = ");
}
/**
* 在Presenter意外销毁的时候被调用,它的调用时机和Activity、Fragment、View中的onSaveInstanceState
* 时机相同
*
* @param outState
*/
public void onSaveInstanceState(Bundle outState) {
Log.e("perfect-mvp","P onSaveInstanceState = ");
}
/**
* 获取V层接口View
*
* @return 返回当前MvpView
*/
public V getMvpView() {
return mView;
}
}
~~~
5. 创建一个代理来管理Presenter的生命周期方法
~~~
/**
* @author 刘镓旗
* @date 2017/11/20
* @description 代理实现类,用来管理Presenter的生命周期,还有和view之间的关联
*/
public class BaseMvpProxy<V extends BaseMvpView, P extends BaseMvpPresenter<V>> implements PresenterProxyInterface<V, P>{
/**
* 获取onSaveInstanceState中bundle的key
*/
private static final String PRESENTER_KEY = "presenter_key";
/**
* Presenter工厂类
*/
private PresenterMvpFactory<V, P> mFactory;
private P mPresenter;
private Bundle mBundle;
private boolean mIsAttchView;
public BaseMvpProxy(PresenterMvpFactory<V, P> presenterMvpFactory) {
this.mFactory = presenterMvpFactory;
}
/**
* 设置Presenter的工厂类,这个方法只能在创建Presenter之前调用,也就是调用getMvpPresenter()之前,如果Presenter已经创建则不能再修改
*
* @param presenterFactory PresenterFactory类型
*/
@Override
public void setPresenterFactory(PresenterMvpFactory<V, P> presenterFactory) {
if (mPresenter != null) {
throw new IllegalArgumentException("这个方法只能在getMvpPresenter()之前调用,如果Presenter已经创建则不能再修改");
}
this.mFactory = presenterFactory;
}
/**
* 获取Presenter的工厂类
*
* @return PresenterMvpFactory类型
*/
@Override
public PresenterMvpFactory<V, P> getPresenterFactory() {
return mFactory;
}
/**
* 获取创建的Presenter
*
* @return 指定类型的Presenter
* 如果之前创建过,而且是以外销毁则从Bundle中恢复
*/
@Override
public P getMvpPresenter() {
Log.e("perfect-mvp","Proxy getMvpPresenter");
if (mFactory != null) {
if (mPresenter == null) {
mPresenter = mFactory.createMvpPresenter();
mPresenter.onCreatePersenter(mBundle == null ? null : mBundle.getBundle(PRESENTER_KEY));
}
}
Log.e("perfect-mvp","Proxy getMvpPresenter = " + mPresenter);
return mPresenter;
}
/**
* 绑定Presenter和view
* @param mvpView
*/
public void onResume(V mvpView) {
getMvpPresenter();
Log.e("perfect-mvp","Proxy onResume");
if (mPresenter != null && !mIsAttchView) {
mPresenter.onAttachMvpView(mvpView);
mIsAttchView = true;
}
}
/**
* 销毁Presenter持有的View
*/
private void onDetachMvpView() {
Log.e("perfect-mvp","Proxy onDetachMvpView = ");
if (mPresenter != null && mIsAttchView) {
mPresenter.onDetachMvpView();
mIsAttchView = false;
}
}
/**
* 销毁Presenter
*/
public void onDestroy() {
Log.e("perfect-mvp","Proxy onDestroy = ");
if (mPresenter != null ) {
onDetachMvpView();
mPresenter.onDestroyPersenter();
mPresenter = null;
}
}
/**
* 意外销毁的时候调用
* @return Bundle,存入回调给Presenter的Bundle和当前Presenter的id
*/
public Bundle onSaveInstanceState() {
Log.e("perfect-mvp","Proxy onSaveInstanceState = ");
Bundle bundle = new Bundle();
getMvpPresenter();
if(mPresenter != null){
Bundle presenterBundle = new Bundle();
//回调Presenter
mPresenter.onSaveInstanceState(presenterBundle);
bundle.putBundle(PRESENTER_KEY,presenterBundle);
}
return bundle;
}
/**
* 意外关闭恢复Presenter
* @param savedInstanceState 意外关闭时存储的Bundler
*/
public void onRestoreInstanceState(Bundle savedInstanceState) {
Log.e("perfect-mvp","Proxy onRestoreInstanceState = ");
Log.e("perfect-mvp","Proxy onRestoreInstanceState Presenter = " + mPresenter);
mBundle = savedInstanceState;
}
}
~~~
6. 最后**V层实现**,首先**实现设置工厂的接口**,然**后创建一个代理并传入默认工厂**,**在V层生命周期中使用代理去实现管理Presenter的生命周期 **
~~~
/**
* @author 刘镓旗
* @date 2017/11/17
* @description 继承自Activity的基类MvpActivity
* 使用代理模式来代理Presenter的创建、销毁、绑定、解绑以及Presenter的状态保存,其实就是管理Presenter的生命周期
*/
public abstract class AbstractMvpActivitiy<V extends BaseMvpView, P extends BaseMvpPresenter<V>> extends Activity implements PresenterProxyInterface<V,P> {
private static final String PRESENTER_SAVE_KEY = "presenter_save_key";
/**
* 创建被代理对象,传入默认Presenter的工厂
*/
private BaseMvpProxy<V,P> mProxy = new BaseMvpProxy<>(PresenterMvpFactoryImpl.<V,P>createFactory(getClass()));
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e("perfect-mvp","V onCreate");
Log.e("perfect-mvp","V onCreate mProxy = " + mProxy);
Log.e("perfect-mvp","V onCreate this = " + this.hashCode());
if(savedInstanceState != null){
mProxy.onRestoreInstanceState(savedInstanceState.getBundle(PRESENTER_SAVE_KEY));
}
}
@Override
protected void onResume() {
super.onResume();
Log.e("perfect-mvp","V onResume");
mProxy.onResume((V) this);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.e("perfect-mvp","V onDestroy = " );
mProxy.onDestroy();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.e("perfect-mvp","V onSaveInstanceState");
outState.putBundle(PRESENTER_SAVE_KEY,mProxy.onSaveInstanceState());
}
@Override
public void setPresenterFactory(PresenterMvpFactory<V, P> presenterFactory) {
Log.e("perfect-mvp","V setPresenterFactory");
mProxy.setPresenterFactory(presenterFactory);
}
@Override
public PresenterMvpFactory<V, P> getPresenterFactory() {
Log.e("perfect-mvp","V getPresenterFactory");
return mProxy.getPresenterFactory();
}
@Override
public P getMvpPresenter() {
Log.e("perfect-mvp","V getMvpPresenter");
return mProxy.getMvpPresenter();
}
}
~~~
最后看一下使用,首先在V层上定义**需要创建的Presenter**,**声明自己模块具体的View接口类型和Presenter类型**,**最后实现自己View接口就ok了**,还有就是**如果要设置自己的Presenter创建工厂,必须在调用onResume方法和getMvpPresenter方法之前设置 **
~~~
//声明需要创建的Presenter
@CreatePresenter(RequestPresenter5.class)
public class MainActivity extends AbstractMvpAppCompatActivity<RequestView5, RequestPresenter5> implements RequestView5 {
@FieldView(R.id.tv_text)
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewFind.bind(this);
//设置自己的Presenter工厂,如果你想自定义的话
// setPresenterFactory(xxx);
if(savedInstanceState != null){
Log.e("perfect-mvp","MainActivity onCreate 测试 = " + savedInstanceState.getString("test") );
}
}
//点击事件
public void request(View view) {
Log.e("perfect-mvp","点击事件");
getMvpPresenter().clickRequest("101010100");
}
@Override
public void requestLoading() {
textView.setText("请求中,请稍后...");
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.e("perfect-mvp","MainActivity onSaveInstanceState 测试");
outState.putString("test","test_save");
}
@Override
public void resultSuccess(WeatherBean result) {
//成功
textView.setText(result.getWeatherinfo().toString());
}
@Override
public void resultFailure(String result) {
//失败
textView.setText(result);
}
}
~~~
这时候**如果界面意外销毁**,**Presenter可以通过重写以下方法进行释放资源,存储数据,和恢复数据**,例如:
~~~
@Override
public void onCreatePersenter(@Nullable Bundle savedState) {
super.onCreatePersenter(savedState);
if(savedState != null){
Log.e("perfect-mvp","RequestPresenter5 onCreatePersenter 测试 = " + savedState.getString("test2") );
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.e("perfect-mvp","RequestPresenter5 onSaveInstanceState 测试 " );
outState.putString("test2","test_save2");
}
@Override
public void onDestroyPersenter() {
super.onDestroyPersenter();
}
~~~
哦了!大功告成,perfect!可能有的人会说这只是Activity,那么Fragment中怎么弄呢,其实是一模一样的,我们将实现全部抽离到了 代理中,那么Fragment中也只需要创建一个代理,然后在生命周期中使用代理调用相应就好了,当然最后我的库中已经实现了Fragment的基类和AppCompatActivity的基类,至于View的如果有使用到的可以自行扩展,再次声明本文只是提供一种思路和封装的方法,并不代表就是最好的,如果有更好的想法和思路可以一起探讨。
最后奉上github地址,还希望可以给个star鼓励一下。再次感谢!
GitHub封装库地址:[perfect-mvp ](https://github.com/ljqloveyou123/perfect-mvp)