從 MVP學(xué)習(xí)代碼封裝 (3) - 抽象 V 層生命周期模板

本系列文章集合:從 MVP學(xué)習(xí)代碼封裝 (1) - 綜述

說在開始

看過上一篇文章的萌新們搪柑,應(yīng)該都熟悉了基本的代碼套路,上一篇文章中 基于 :base接口 - abs 基類 - 實現(xiàn)類的封裝套路索烹,這個不管放到哪里工碾,我們寫框架都基本是這個樣子,這是用來搭建框架的基本架構(gòu)的百姓,但是呢渊额,我們寫自己的框架畢竟是對某一類 / 一些功能的封裝,如何規(guī)劃好一個框架中功能呢垒拢,我們可是要實現(xiàn)易閱讀旬迹,易修改,易擴展的功能代碼的求类,況且要是需要實現(xiàn)的功能多的話奔垦,如何做好那可是個麻煩事啊。

通過本篇呢尸疆,我想讓給萌新們提供一個思路:使用模板設(shè)計模式椿猎,把單個功能抽象成一個模板接口,然后做具體邏輯實現(xiàn)仓技,由框架控制層創(chuàng)建/持有某個功能的具體實現(xiàn)鸵贬,既可以做到合理劃分功能到單一類,在框架控制層中也很容易做某個功能的實現(xiàn)類替換脖捻,代碼解耦了阔逼,也方便擴展替換了,而且最重要的是容易閱讀了地沮,修改起來方便很多的嗜浮,不會到頭來自己看不懂自己的代碼了羡亩。

所以說不論是框架封裝,但是最簡單的膽碼封裝危融,處處都體現(xiàn)出設(shè)計模式的思想應(yīng)用在里面畏铆,學(xué)好設(shè)計模式是我們的必須要做到的,我都認為設(shè)計模式是 java 基礎(chǔ)中的必會技能了吉殃。不熟悉的萌新們抓緊時間啦辞居,我也是最近才開始學(xué)習(xí)的,不足之處大家多留言啊蛋勺,歡迎打臉瓦灶。


話接上文

先來看看新的 UML 類圖,不得不承認我畫 UML 的水平實在是太 low 了抱完,另外我畫的就是個示意圖贼陶,類,接口里面方法沒寫全巧娱,詳細去看代碼:


Snip20171216_4.png
  1. 模板代碼抽象的都是可變的部分碉怔,留下固定的部分。這里我們需要抽象出的模板代碼是針對 V 層生命周期中可以的部分禁添,具體我們需要針對 3中 View 類型:
  • activity
  • fragment
  • view

這3種 view 類型撮胧,都有各自不同的生命周期函數(shù),所以我們需要抽象出3個模板接口:

  • ILifecycleProxy 根接口老翘,用來指定泛型的
  • interface IActivityLifecycleProxy extends ILifecycleProxy
  • interface IFragmentLifecycleProxy extends ILifecycleProxy
  • interface ICustomeViewLifecycleProxy extends ILifecycleProxy

具體的我們先抽象一個根接口 ILifecycleProxy 趴樱,這樣方面我們使用泛型,然后用具體的類型去替換酪捡。3個具體的接口分別對應(yīng)3種 view 類型

  1. 我們在 BasePersenter 這個 P 層的abs 基類中叁征,我們添加聲明周期類型的泛型,用 ILifecycleProxy 這個聲明周期根接口這個類型逛薇。
public abstract class BasePersenter<V extends IBaseView, L extends ILifecycleProxy>
  1. 我思考過后呢捺疼,決定把抽象出來的可變的view 中生命周期的代碼由 P 層對象來實現(xiàn),在 MVP 架構(gòu)中 P 層對象就是相當(dāng)于最外層的控制對象的永罚。然后根據(jù) View 類型的不同啤呼, P 層需要實現(xiàn)不同的生命周期接口,鑒于生命周期接口差別的巨大和合理的設(shè)計呢袱,我在這里根據(jù) View 類型一一對應(yīng)生成多個 P 層 abs 基類來適應(yīng) View 類型官扣。

大家注意泛型的使用,不同的 Persenter 類型在繼承 BasePersenter 時羞福,指定了不同的對應(yīng)的 view 類型的生命周期接口惕蹄,然后 Persenter 實現(xiàn)了這個生命周期接口。我們在具體的 Persenter 對象中的對應(yīng)生命周期方法中寫自己的邏輯即可,這里我的代碼也是演示性質(zhì)的卖陵,實際上是由缺漏的遭顶,大家根據(jù)實際需求去修改吧,生命周期函數(shù)太多了泪蔫。

  • BaseActivityPersenter
public class BaseActivityPersenter<V extends BaseActivity> extends BasePersenter<V, IActivityLifecycleProxy> implements IActivityLifecycleProxy
  • BaseFragmentPersenter
public class BaseFragmentPersenter<V extends BaseFragment> extends BasePersenter<V, IFragmentLifecycleProxy> implements IFragmentLifecycleProxy
  • BaseCustomeViewPersenter
public class BaseCustomeViewPersenter<V extends BaseCustomeView> extends BasePersenter<V,ICustomeViewLifecycleProxy> implements ICustomeViewLifecycleProxy
  1. 在 V 層 abs 基類中棒旗,合適的地方初始化這個生命周期函數(shù)接口對象出來,然后在需要的生命周期函數(shù)中去執(zhí)行這個生命周期函數(shù)模版對象的相應(yīng)方法撩荣,我以Activity具個例子铣揉,更多的去看demo
public abstract class BaseActivity<V extends BaseActivity, P extends BaseActivityPersenter<V>> extends AppCompatActivity implements IBaseView {

    private P mBasePersenter;

    protected abstract P createPersenter();

    private IActivityLifecycleProxy lifecycleProxy;

    public P getPersenter() {
        return mBasePersenter;
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mBasePersenter = createPersenter();
        mBasePersenter.attachView((V) this);

        lifecycleProxy = getPersenter().createlLifecycleProxy();
//        lifecycleProxy = (IActivityLifecycleProxy) Proxy.newProxyInstance(lifecycleProxy.getClass().getClassLoader(), lifecycleProxy.getClass().getInterfaces(), new NotNullnvocationHandler(lifecycleProxy));

        lifecycleProxy.onCreate(savedInstanceState);
    }

    @Override
    protected void onPause() {
        lifecycleProxy.onPause();
        super.onPause();
    }

    @Override
    protected void onResume() {
        lifecycleProxy.onResume();
        super.onResume();
    }

    @Override
    protected void onStop() {
        lifecycleProxy.onStop();
        super.onStop();
    }

    @Override
    protected void onStart() {
        lifecycleProxy.onStart();
        super.onStart();
    }

    @Override
    protected void onRestart() {
        lifecycleProxy.onStart();
        super.onRestart();
    }

    @Override
    protected void onNewIntent(Intent intent) {
        lifecycleProxy.onNewIntent(intent);
        super.onNewIntent(intent);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        lifecycleProxy.onSaveInstanceState(outState);
        super.onSaveInstanceState(outState);
    }

    @Override
    public void onBackPressed() {
        if (lifecycleProxy.onBackPressed()) {
            return;
        }
        super.onBackPressed();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        lifecycleProxy.onRequestPermissionsResult(requestCode, permissions, grantResults);
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        lifecycleProxy.onActivityResult(requestCode, resultCode, data);
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    protected void onDestroy() {
        lifecycleProxy.onDestroy();

        if (mBasePersenter != null) {
            mBasePersenter.detachView();
        }
        super.onDestroy();
    }
}

這里我想說一下,我想用動態(tài)代理處理一下 IActivityLifecycleProxy 這個屬性餐曹,應(yīng)對這個對象意外為 null 時的情況老速,但是不知道為啥就是報錯,報類型轉(zhuǎn)換錯誤


最后

基本上代碼的思路就是這些了凸主,寫完之后,我又掠了掠了思路额湘,的確是對自己的代碼封裝水平提神很有幫助卿吐,程序員這一行真的是用大量的思考和練習(xí)時間堆積出來的。

具體來說代碼很簡單锋华,雖然看起來很簡單嗡官,但是在寫的時候可是報了不少錯啊,主要是聲明周期太多了毯焕,需要考慮在合適的點初始化代碼啊衍腥。

另外在思考時,我考慮 MVP 架構(gòu)是更應(yīng)該說是一種代碼書寫規(guī)范纳猫,一個 V 的就應(yīng)該對應(yīng)一個 P婆咸,P 在不同的 V 之間復(fù)用,這個是不切實際的芜辕,也是不符合設(shè)計規(guī)范的尚骄,不同的 V 之間實際是由大量差異的,對應(yīng) V 來說侵续,他的 P 就是專屬與自己的倔丈,這在 MVP 的設(shè)計來說就是這樣的。若是不同的 V 的 P 之間有相同的代碼邏輯状蜗,那也是把系相同的邏輯代碼再封裝成工具對象需五,而不是去思考如何復(fù)用 P 。所提體現(xiàn)在這里的是在具體的 V層對象時轧坎,傳入的 V 的泛型就是自己的類型宏邮,具體例子

public class NewsActivity extends BaseActivity<NewsActivity, NewsActivityPersenter> implements INewsView

NewsActivity 中,之前 V 的泛型使用的具體的 INewsView 這個業(yè)務(wù)接口,這個業(yè)務(wù)接口是繼承的 V 層根接口 IBaseView的蜀铲,現(xiàn)在我們直接傳自己就可以边琉,因為對于 P 來說,我只需要針對一個類型 V 的就行记劝,沒機會在 V 直接復(fù)用变姨,在實際使用中 V,可以會實現(xiàn)大量業(yè)務(wù)接口厌丑,這樣做我們在 P 層寫具體業(yè)務(wù)邏輯時會省略 V 對象在不同業(yè)務(wù)接口之間來回強轉(zhuǎn)類型定欧。

代碼部分是demo 中 step2_1 這部分。


Snip20171209_48.png

最后是項目地址: BW-MVPDemo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末怒竿,一起剝皮案震驚了整個濱河市砍鸠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌耕驰,老刑警劉巖爷辱,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異朦肘,居然都是意外死亡饭弓,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進店門媒抠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弟断,“玉大人,你說我怎么就攤上這事趴生》浚” “怎么了?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵苍匆,是天一觀的道長刘急。 經(jīng)常有香客問我,道長浸踩,這世上最難降的妖魔是什么排霉? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮民轴,結(jié)果婚禮上攻柠,老公的妹妹穿的比我還像新娘。我一直安慰自己后裸,他們只是感情好瑰钮,可當(dāng)我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著微驶,像睡著了一般浪谴。 火紅的嫁衣襯著肌膚如雪开睡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天苟耻,我揣著相機與錄音篇恒,去河邊找鬼。 笑死凶杖,一個胖子當(dāng)著我的面吹牛胁艰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播智蝠,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼腾么,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了杈湾?” 一聲冷哼從身側(cè)響起解虱,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎漆撞,沒想到半個月后殴泰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡浮驳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年悍汛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抹恳。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖署驻,靈堂內(nèi)的尸體忽然破棺而出奋献,到底是詐尸還是另有隱情,我是刑警寧澤旺上,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布瓶蚂,位于F島的核電站,受9級特大地震影響宣吱,放射性物質(zhì)發(fā)生泄漏窃这。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一征候、第九天 我趴在偏房一處隱蔽的房頂上張望杭攻。 院中可真熱鬧,春花似錦疤坝、人聲如沸兆解。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锅睛。三九已至埠巨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間现拒,已是汗流浹背辣垒。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留印蔬,地道東北人勋桶。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像扛点,于是被迫代替她去往敵國和親哥遮。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,652評論 2 354