概述
本文重點(diǎn)是封裝一個(gè)高級(jí)MVP架構(gòu),會(huì)詳細(xì)的講解如何一步步從無(wú)到有的封裝成一個(gè)高級(jí)MVP架構(gòu)過(guò)程首昔。
文章會(huì)以5個(gè)部分來(lái)整體優(yōu)化封裝MVP织阅,也是一個(gè)從無(wú)到有的過(guò)程
一便瑟、不使用MVP的代碼
二坟募、最簡(jiǎn)單的MVP實(shí)現(xiàn)
三岛蚤、解決MVP內(nèi)存泄露
四、簡(jiǎn)單抽象-解決MVP代碼冗余
五懈糯、高級(jí)抽象-使用注解涤妒、工廠模式、代理模式赚哗、策略模式整體解決代碼冗余她紫、內(nèi)存泄露、Presenter生命周期以及數(shù)據(jù)存儲(chǔ)問(wèn)題
不廢話了屿储,進(jìn)入正題贿讹。
場(chǎng)景:假如界面有一個(gè)按鈕,點(diǎn)擊后請(qǐng)求數(shù)據(jù)够掠,然后成功后將返回的數(shù)據(jù)設(shè)置到一個(gè)Textview中
不使用MVP的代碼
一民褂、不使用MVP的代碼,一般我們會(huì)這么寫(xiě)
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);
}
//按鈕點(diǎn)擊事件
public void request(View view) {
clickRequest("101010100");
}
//發(fā)起請(qǐng)求
public void clickRequest(final String cityId) {
//請(qǐng)求接口
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);
//請(qǐng)求
Call<WeatherBean> weatherBeanCall = apiService.requestWeather(cityId);
weatherBeanCall.enqueue(new Callback<WeatherBean>() {
@Override
public void onResponse(Call<WeatherBean> call, Response<WeatherBean> response) {
//請(qǐng)求成功
textView.setText(response.body().getWeatherinfo().toString());
}
@Override
public void onFailure(Call<WeatherBean> call, Throwable t) {
//請(qǐng)求失敗
}
});
}
}
上面的代碼是最原始的寫(xiě)法,下面我們使用最簡(jiǎn)單的MVP模式來(lái)改造這個(gè)代碼疯潭。
最簡(jiǎn)單的MVP實(shí)現(xiàn)
思路如下:
1赊堪、首先我們先定義一個(gè)接口,用來(lái)規(guī)定針對(duì)這個(gè)界面邏輯View需要作出的動(dòng)作的接口竖哩。
2哭廉、讓Activity實(shí)現(xiàn)這個(gè)接口中的方法,也就是V層
3期丰、創(chuàng)建一個(gè)類(lèi)群叶,用來(lái)封裝之前的網(wǎng)絡(luò)請(qǐng)求過(guò)程,也就是M層
4钝荡、再創(chuàng)建一個(gè)類(lèi),用來(lái)處理M層和V層之間的通信舶衬,也就是P層
下面來(lái)實(shí)現(xiàn)一下:
1埠通、首先我們先定義一個(gè)接口,用來(lái)規(guī)定針對(duì)這個(gè)界面邏輯View需要作出的動(dòng)作的接口逛犹。
/**
* @author
* @date 2017/11/16
* @description V層接口端辱,定義V層需要作出的動(dòng)作的接口
*/
public interface RequestView1 {
//請(qǐng)求時(shí)展示加載
void requestLoading();
//請(qǐng)求成功
void resultSuccess(WeatherBean result);
//請(qǐng)求失敗
void resultFailure(String result);
}
2、讓Activity實(shí)現(xiàn)這個(gè)接口中的方法虽画,也就是V層
/**
* 第二步:對(duì)應(yīng)demo1
* 2舞蔽,最簡(jiǎn)單的mvp模式,
* 1.Activity需要實(shí)現(xiàn)v層接口
* 2.Persenter需要持有v層引用和m層引用
* 3.在實(shí)現(xiàn)類(lèi)view中創(chuàng)建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);
//創(chuàng)建Presenter
presenter = new RequestPresenter1(this);
}
//點(diǎn)擊事件
public void request(View view) {
presenter.clickRequest("101010100");
}
//請(qǐng)求時(shí)加載
@Override
public void requestLoading() {
textView.setText("請(qǐng)求中,請(qǐng)稍后...");
}
//請(qǐng)求成功
@Override
public void resultSuccess(WeatherBean result) {
//成功
textView.setText(result.getWeatherinfo().toString());
}
//請(qǐng)求失敗
@Override
public void resultFailure(String result) {
//失敗
textView.setText(result);
}
}
3、創(chuàng)建一個(gè)類(lèi)码撰,用來(lái)封裝之前的網(wǎng)絡(luò)請(qǐng)求過(guò)程渗柿,也就是M層
/**
* @description M層 數(shù)據(jù)層
*/
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){
//請(qǐng)求接口
Retrofit retrofit = new Retrofit.Builder()
//代表root地址
.baseUrl(BASE_URL)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiService apiService = retrofit.create(ApiService.class);
//請(qǐng)求
Call<WeatherBean> weatherBeanCall = apiService.requestWeather(detailId);
weatherBeanCall.enqueue(callback);
}
}
4、再創(chuàng)建一個(gè)類(lèi),用來(lái)處理M層和V層之間的通信朵栖,也就是P層
/**
* @description P層
* 特點(diǎn):需要持有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){
//請(qǐng)求時(shí)顯示加載
mRequestView.requestLoading();
//模擬耗時(shí)颊亮,可以展示出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模式的使用了陨溅,可是這樣寫(xiě)會(huì)內(nèi)存泄露终惑,因?yàn)槿绻诰W(wǎng)絡(luò)請(qǐng)求的過(guò)程中Activity就關(guān)閉了,Presenter還持有了V層的引用门扇,也就是MainActivity雹有,就會(huì)內(nèi)存泄露。
解決MVP內(nèi)存泄露
下面就來(lái)解決這個(gè)問(wèn)題臼寄,我們將P層和V層的關(guān)聯(lián)抽出兩個(gè)方法霸奕,一個(gè)綁定,一個(gè)解綁脯厨,在需要的時(shí)候進(jìn)行綁定V層铅祸,不需要的時(shí)候進(jìn)行解綁就可以了。
我們只需要修改上面Presenter中的構(gòu)造代碼合武,不需要在構(gòu)造中傳遞V層了临梗,然后再寫(xiě)一個(gè)綁定和解綁的方法,最后修改Activity創(chuàng)建Presenter時(shí)進(jìn)行綁定稼跳,在onDestroy中進(jìn)行解綁盟庞。
修改后的Presenter:
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;
}
/**
* 取消網(wǎng)絡(luò)請(qǐng)求
*/
public void interruptHttp(){
mMode.interruptHttp();
}
}
修改后的MainActivity:
/**
* 第三步:對(duì)應(yīng)demo2
* 上面的問(wèn)題:
* 1.是會(huì)內(nèi)存泄露,因?yàn)閜ersenter一直持有Activity汤善,如果一個(gè)發(fā)了一個(gè)請(qǐng)求什猖,
* 但是網(wǎng)絡(luò)有點(diǎn)慢,這個(gè)時(shí)候退出Activity红淡,那么請(qǐng)求回來(lái)后還是會(huì)調(diào)用
* Activity的回調(diào)方法不狮,這里還是因?yàn)橐恢背钟械膯?wèn)題
* 2.如果已經(jīng)退出了當(dāng)前界面,這個(gè)請(qǐng)求也沒(méi)有用了在旱,這個(gè)時(shí)候我們可以斷開(kāi)請(qǐng)求
* <p>
* 解決問(wèn)題:
* 1.增加綁定和解綁的方法來(lái)解決內(nèi)存泄露和退出后還會(huì)回調(diào)的問(wèn)題
* 2摇零、增加斷開(kāi)網(wǎng)絡(luò)連接的方法
*/
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("請(qǐng)求中,請(qǐng)稍后...");
}
@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();
}
}
這樣我們就解決了內(nèi)存泄露的問(wèn)題,但是這樣還是不完美桶蝎,應(yīng)用中肯定不可能只有一個(gè)模塊驻仅,每個(gè)模塊都對(duì)應(yīng)著一個(gè)V層和P層,那這樣的話每個(gè)Presenter中都要定義綁定和解綁的方法登渣,而Activity中對(duì)應(yīng)的也要調(diào)用這綁定和解綁的兩個(gè)方法噪服,代碼冗余。
簡(jiǎn)單抽象-解決MVP代碼冗余
針對(duì)這個(gè)問(wèn)題我們可以抽取出一個(gè)基類(lèi)的Presenter和一個(gè)基類(lèi)的Activity來(lái)做這個(gè)事情胜茧,讓子類(lèi)不用在寫(xiě)這些重復(fù)的代碼粘优。但是問(wèn)題又來(lái)了,既然是基類(lèi),肯定不止有一個(gè)子類(lèi)來(lái)繼承基類(lèi)敬飒,那么也就是說(shuō)子類(lèi)當(dāng)中定義的View接口和需要?jiǎng)?chuàng)建的Presenter都不相同邪铲,我們肯定在基類(lèi)當(dāng)中不能寫(xiě)死吧,那就使用泛型來(lái)設(shè)計(jì)无拗。
思路:
1.創(chuàng)建一個(gè)基類(lèi)View带到,讓所有View接口都必須實(shí)現(xiàn),這個(gè)View可以什么都不做只是用來(lái)約束類(lèi)型的
2.創(chuàng)建一個(gè)基類(lèi)的Presenter,在類(lèi)上規(guī)定View泛型英染,然后定義綁定和解綁的抽象方法揽惹,讓子類(lèi)去實(shí)現(xiàn),對(duì)外在提供一個(gè)獲取View的方法四康,
讓子類(lèi)直接通過(guò)方法來(lái)獲取View
3.創(chuàng)建一個(gè)基類(lèi)的Activity搪搏,聲明一個(gè)創(chuàng)建Presenter的抽象方法,因?yàn)橐獛妥宇?lèi)去綁定和解綁那么就需要拿到子類(lèi)的Presenter才行闪金,但是又不能隨便一個(gè)類(lèi)都能綁定的疯溺,因?yàn)橹挥谢?lèi)的Presenter中才定義了綁定和解綁的方法,所以同樣的在類(lèi)上可以聲明泛型在哎垦,方法上使用泛型來(lái)達(dá)到目的囱嫩。
4.修改Presenter和Activity中的代碼,各自繼承自己的基類(lèi)并去除重復(fù)代碼
實(shí)現(xiàn)步驟:
1.創(chuàng)建一個(gè)基類(lèi)View漏设,讓所有View接口都必須實(shí)現(xiàn)
/**
* @author
* @date 2017/11/17
* @description 所有mvpView的父接口
*/
public interface IMvpBaseView4 {
}
2.創(chuàng)建一個(gè)基類(lèi)的Presenter墨闲,在類(lèi)上規(guī)定View泛型,然后定義綁定和解綁的方法郑口,對(duì)外在提供一個(gè)獲取View的方法鸳碧,讓子類(lèi)直接通過(guò)方法來(lái)獲取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.創(chuàng)建一個(gè)基類(lèi)的Activity,聲明一個(gè)創(chuàng)建Presenter的抽象方法犬性,因?yàn)橐獛妥宇?lèi)去綁定和解綁那么就需要拿到子類(lèi)的Presenter才行瞻离,但是又不能隨便一個(gè)類(lèi)都能綁定的,因?yàn)橹挥谢?lèi)的Presenter中才定義了綁定和解綁的方法乒裆,所以同樣的在類(lèi)上可以聲明泛型在方法上使用泛型來(lái)達(dá)到目的
/**
* @description MvpActivity
* 指定子類(lèi)具體的View必須繼承自IMvpBaseView4
* 指定子類(lèi)具體的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);
//創(chuàng)建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();
}
}
/**
* 創(chuàng)建Presenter
* @return 子類(lèi)自己需要的Presenter
*/
protected abstract P createPresenter();
/**
* 獲取Presenter
* @return 返回子類(lèi)創(chuàng)建的Presenter
*/
public P getPresenter() {
return presenter;
}
}
4.修改Presenter和Activity中的代碼琐脏,各自繼承自己的基類(lèi)并去除重復(fù)代碼
修改后的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();
}
//模擬網(wǎng)絡(luò)延遲,可以顯示出加載中
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();
}
//點(diǎn)擊事件
public void request(View view) {
getPresenter().clickRequest("101010100");
}
@Override
public void requestLoading() {
textView.setText("請(qǐng)求中,請(qǐng)稍后...");
}
@Override
public void resultSuccess(WeatherBean result) {
//成功
textView.setText(result.getWeatherinfo().toString());
}
@Override
public void resultFailure(String result) {
//失敗
textView.setText(result);
}
}
到這里完美了嗎缸兔?沒(méi)有,還可以再抽吹艇,來(lái)分析一下還有哪些不完美的地方以及如何再優(yōu)化惰蜜。
進(jìn)一步的優(yōu)化
高級(jí)抽象-使用注解、工廠模式受神、代理模式抛猖、策略模式整體解決代碼冗余、內(nèi)存泄露、Presenter生命周期以及數(shù)據(jù)存儲(chǔ)問(wèn)題
1.每個(gè)子類(lèi)都要重寫(xiě)父類(lèi)創(chuàng)建Presenter的方法财著,創(chuàng)建一個(gè)Presenter并返回联四,這一步我們也可以讓父類(lèi)幫忙干了,怎么做呢撑教?
我們可以采用注解的方式朝墩,在子類(lèi)上聲明一個(gè)注解并注明要?jiǎng)?chuàng)建的類(lèi)型,剩下的事情就讓父類(lèi)去做了,但是父類(lèi)得考慮如果子類(lèi)不想這么干怎么辦伟姐,那也還是不能寫(xiě)死吧收苏,可以使用策略模式加工廠模式來(lái)實(shí)現(xiàn),我們默認(rèn)使用這種注解的工廠 愤兵,但是如果子類(lèi)不喜歡可以通過(guò)父類(lèi)提供的一個(gè)方法來(lái)創(chuàng)建自己的工廠鹿霸。
2.Presenter真正的創(chuàng)建過(guò)程,我們可以將它放到真正使用Presenter的時(shí)候再創(chuàng)建秆乳,這樣的話可以稍微優(yōu)化一下性能問(wèn)題
3.界面有可能會(huì)意外銷(xiāo)毀并重建懦鼠,Activity、Fragment屹堰、View都可以在銷(xiāo)毀的時(shí)候通過(guò)onDestroy釋放一些資源并在onSaveInstanceState方法中存儲(chǔ)一些數(shù)據(jù)然后在重建的時(shí)候恢復(fù)肛冶,但是有可能Presenter中也需要釋放一些資源存儲(chǔ)一些數(shù)據(jù),那么上面的結(jié)構(gòu)就不能滿足了双藕,我們可以給Presenter增加生命周期的方法淑趾,讓Presenter和V層生命周期同步就可以做到了
4.第三步中我們又給Presenter加入了一些生命周期的方法,再加上Presenter的創(chuàng)建綁定和解綁的方法忧陪,那么如果我們?cè)趧?chuàng)建一個(gè)MvpFragment基類(lèi)扣泊,或者View的基類(lèi)那么這么多的代碼豈不是都要copy一份嗎,而且看起來(lái)也很不清晰嘶摊,這里我們可以采用代理模式來(lái)優(yōu)化一下延蟹。
好了下面來(lái)實(shí)現(xiàn):
1.我們既然要采用工廠模式才創(chuàng)建Presenter,那么我們首先來(lái)創(chuàng)建一個(gè)工廠接口
/**
* @author
* @date 2017/11/17
* @description Presenter工廠接口
*/
public interface PresenterMvpFactory<V extends BaseMvpView,P extends BaseMvpPresenter<V>> {
/**
* 創(chuàng)建Presenter的接口方法
* @return 需要?jiǎng)?chuàng)建的Presenter
*/
P createMvpPresenter();
}
2.然后我們需要?jiǎng)?chuàng)建一個(gè)默認(rèn)使用注解創(chuàng)建的工廠叶堆,那么首先要?jiǎng)?chuàng)建一個(gè)注解
注解:
/**
* @description 標(biāo)注創(chuàng)建Presenter的注解
*/
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface CreatePresenter {
Class<? extends BaseMvpPresenter> value();
}
注解工廠:
/**
* @author
* @date 2017/11/17
* @description Presenter工廠實(shí)現(xiàn)類(lèi)
*/
public class PresenterMvpFactoryImpl<V extends BaseMvpView, P extends BaseMvpPresenter<V>> implements PresenterMvpFactory<V, P> {
/**
* 需要?jiǎng)?chuàng)建的Presenter的類(lèi)型
*/
private final Class<P> mPresenterClass;
/**
* 根據(jù)注解創(chuàng)建Presenter的工廠實(shí)現(xiàn)類(lèi)
* @param viewClazz 需要?jiǎng)?chuàng)建Presenter的V層實(shí)現(xiàn)類(lèi)
* @param <V> 當(dāng)前View實(shí)現(xiàn)的接口類(lèi)型
* @param <P> 當(dāng)前要?jiǎng)?chuàng)建的Presenter類(lèi)型
* @return 工廠類(lèi)
*/
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創(chuàng)建失敗!阱飘,檢查是否聲明了@CreatePresenter(xx.class)注解");
}
}
}
3.我們說(shuō)了不能寫(xiě)死這個(gè)工廠,那么我們需要使用者可以自定義虱颗,那么我們還需要給使用者提供一個(gè)設(shè)置的方法沥匈,我們定義一個(gè)接口提供設(shè)置工廠、獲取工廠忘渔、獲取Presenter的方法高帖,然后讓V層來(lái)實(shí)現(xiàn)這個(gè)接口,這樣V層的子類(lèi)就可以通過(guò)相應(yīng)的方法使用了
/**
* @author
* @date 2017/11/20
* @description 代理接口
*/
public interface PresenterProxyInterface<V extends BaseMvpView,P extends BaseMvpPresenter<V>> {
/**
* 設(shè)置創(chuàng)建Presenter的工廠
* @param presenterFactory PresenterFactory類(lèi)型
*/
void setPresenterFactory(PresenterMvpFactory<V,P> presenterFactory);
/**
* 獲取Presenter的工廠類(lèi)
* @return 返回PresenterMvpFactory類(lèi)型
*/
PresenterMvpFactory<V,P> getPresenterFactory();
/**
* 獲取創(chuàng)建的Presenter
* @return 指定類(lèi)型的Presenter
*/
P getMvpPresenter();
}
4.給Presenter增加生命周期的方法
/**
* @author
* @date 2017/11/17
* @description 所有Presenter的基類(lèi)畦粮,并不強(qiáng)制實(shí)現(xiàn)這些方法散址,有需要在重寫(xiě)
*/
public class BaseMvpPresenter<V extends BaseMvpView> {
/**
* V層view
*/
private V mView;
/**
* Presenter被創(chuàng)建后調(diào)用
*
* @param savedState 被意外銷(xiāo)毀后重建后的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被銷(xiāo)毀時(shí)調(diào)用
*/
public void onDestroyPersenter() {
Log.e("perfect-mvp","P onDestroy = ");
}
/**
* 在Presenter意外銷(xiāo)毀的時(shí)候被調(diào)用乖阵,它的調(diào)用時(shí)機(jī)和Activity、Fragment预麸、View中的onSaveInstanceState
* 時(shí)機(jī)相同
*
* @param outState
*/
public void onSaveInstanceState(Bundle outState) {
Log.e("perfect-mvp","P onSaveInstanceState = ");
}
/**
* 獲取V層接口View
*
* @return 返回當(dāng)前MvpView
*/
public V getMvpView() {
return mView;
}
}
5.創(chuàng)建一個(gè)代理來(lái)管理Presenter的生命周期方法
/**
* @author
* @date 2017/11/20
* @description 代理實(shí)現(xiàn)類(lèi)瞪浸,用來(lái)管理Presenter的生命周期,還有和view之間的關(guān)聯(lián)
*/
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工廠類(lèi)
*/
private PresenterMvpFactory<V, P> mFactory;
private P mPresenter;
private Bundle mBundle;
private boolean mIsAttchView;
public BaseMvpProxy(PresenterMvpFactory<V, P> presenterMvpFactory) {
this.mFactory = presenterMvpFactory;
}
/**
* 設(shè)置Presenter的工廠類(lèi),這個(gè)方法只能在創(chuàng)建Presenter之前調(diào)用,也就是調(diào)用getMvpPresenter()之前吏祸,如果Presenter已經(jīng)創(chuàng)建則不能再修改
*
* @param presenterFactory PresenterFactory類(lèi)型
*/
@Override
public void setPresenterFactory(PresenterMvpFactory<V, P> presenterFactory) {
if (mPresenter != null) {
throw new IllegalArgumentException("這個(gè)方法只能在getMvpPresenter()之前調(diào)用对蒲,如果Presenter已經(jīng)創(chuàng)建則不能再修改");
}
this.mFactory = presenterFactory;
}
/**
* 獲取Presenter的工廠類(lèi)
*
* @return PresenterMvpFactory類(lèi)型
*/
@Override
public PresenterMvpFactory<V, P> getPresenterFactory() {
return mFactory;
}
/**
* 獲取創(chuàng)建的Presenter
*
* @return 指定類(lèi)型的Presenter
* 如果之前創(chuàng)建過(guò),而且是以外銷(xiāo)毀則從Bundle中恢復(fù)
*/
@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;
}
}
/**
* 銷(xiāo)毀Presenter持有的View
*/
private void onDetachMvpView() {
Log.e("perfect-mvp","Proxy onDetachMvpView = ");
if (mPresenter != null && mIsAttchView) {
mPresenter.onDetachMvpView();
mIsAttchView = false;
}
}
/**
* 銷(xiāo)毀Presenter
*/
public void onDestroy() {
Log.e("perfect-mvp","Proxy onDestroy = ");
if (mPresenter != null ) {
onDetachMvpView();
mPresenter.onDestroyPersenter();
mPresenter = null;
}
}
/**
* 意外銷(xiāo)毀的時(shí)候調(diào)用
* @return Bundle犁罩,存入回調(diào)給Presenter的Bundle和當(dāng)前Presenter的id
*/
public Bundle onSaveInstanceState() {
Log.e("perfect-mvp","Proxy onSaveInstanceState = ");
Bundle bundle = new Bundle();
getMvpPresenter();
if(mPresenter != null){
Bundle presenterBundle = new Bundle();
//回調(diào)Presenter
mPresenter.onSaveInstanceState(presenterBundle);
bundle.putBundle(PRESENTER_KEY,presenterBundle);
}
return bundle;
}
/**
* 意外關(guān)閉恢復(fù)Presenter
* @param savedInstanceState 意外關(guān)閉時(shí)存儲(chǔ)的Bundler
*/
public void onRestoreInstanceState(Bundle savedInstanceState) {
Log.e("perfect-mvp","Proxy onRestoreInstanceState = ");
Log.e("perfect-mvp","Proxy onRestoreInstanceState Presenter = " + mPresenter);
mBundle = savedInstanceState;
}
}
6.最后V層實(shí)現(xiàn)齐蔽,首先實(shí)現(xiàn)設(shè)置工廠的接口,然后創(chuàng)建一個(gè)代理并傳入默認(rèn)工廠床估,在V層生命周期中使用代理去實(shí)現(xiàn)管理Presenter的生命周期
/**
* @author
* @date 2017/11/17
* @description 繼承自Activity的基類(lèi)MvpActivity
* 使用代理模式來(lái)代理Presenter的創(chuàng)建含滴、銷(xiāo)毀、綁定丐巫、解綁以及Presenter的狀態(tài)保存,其實(shí)就是管理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";
/**
* 創(chuàng)建被代理對(duì)象,傳入默認(rèn)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層上定義需要?jiǎng)?chuàng)建的Presenter,聲明自己模塊具體的View接口類(lèi)型和Presenter類(lèi)型递胧,最后實(shí)現(xiàn)自己View接口就ok了碑韵,還有就是如果要設(shè)置自己的Presenter創(chuàng)建工廠,必須在調(diào)用onResume方法和getMvpPresenter方法之前設(shè)置
//聲明需要?jiǎng)?chuàng)建的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);
//設(shè)置自己的Presenter工廠缎脾,如果你想自定義的話
// setPresenterFactory(xxx);
if(savedInstanceState != null){
Log.e("perfect-mvp","MainActivity onCreate 測(cè)試 = " + savedInstanceState.getString("test") );
}
}
//點(diǎn)擊事件
public void request(View view) {
Log.e("perfect-mvp","點(diǎn)擊事件");
getMvpPresenter().clickRequest("101010100");
}
@Override
public void requestLoading() {
textView.setText("請(qǐng)求中,請(qǐng)稍后...");
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.e("perfect-mvp","MainActivity onSaveInstanceState 測(cè)試");
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);
}
}
這時(shí)候如果界面意外銷(xiāo)毀,Presenter可以通過(guò)重寫(xiě)以下方法進(jìn)行釋放資源祝闻,存儲(chǔ)數(shù)據(jù),和恢復(fù)數(shù)據(jù)遗菠,例如:
@Override
public void onCreatePersenter(@Nullable Bundle savedState) {
super.onCreatePersenter(savedState);
if(savedState != null){
Log.e("perfect-mvp","RequestPresenter5 onCreatePersenter 測(cè)試 = " + savedState.getString("test2") );
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.e("perfect-mvp","RequestPresenter5 onSaveInstanceState 測(cè)試 " );
outState.putString("test2","test_save2");
}
@Override
public void onDestroyPersenter() {
super.onDestroyPersenter();
}
哦了联喘!大功告成,perfect辙纬!