<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                原文出處:[高級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)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看