Android項(xiàng)目基本架構(gòu)(三) Retrofit + Rx +OkHttp + MVP

image.png

前言


  • 好了哈扮,接下來就要和大家說說 Retrofit + Rx +OkHttp + MVP 了纬纪,這些都是老套路了,關(guān)于Retrofit + Rx 的用法灶泵,我已經(jīng)在之前的文章里面講解過了育八,不知道的朋友可以先移步看看:
  • Android中用Retrofit+Rxjava搭建網(wǎng)絡(luò)請求
  • Retrofit的深入使用
  • 那么,今天的重點(diǎn)就是MVP模式的構(gòu)建了赦邻。

MVP實(shí)現(xiàn)


  • 關(guān)于MVP和MVC相關(guān)的概念相信大家都知道髓棋,就算不知道的百度一下也有很多,這里就不多說了惶洲,重點(diǎn)是如何實(shí)現(xiàn)這樣的架構(gòu)按声,并且使用起來方便。

  • 首先恬吕,是相關(guān)的基類的創(chuàng)建 BaseMVPPresenter签则、BaseMVPView。不多說铐料,上代碼

    /**
     * MVP Presenter基類
     *
     * @param <V> MVP View 繼承 {@link BaseMVPView}
     * @param <M> MVP Module
     *
     * @author 王杰
     */
     public class BaseMVPPresenter<V extends BaseMVPView, M> {
    
         /** View對象 */
         protected V mView;
         /** Module對象 */
         @Inject
         protected M mModule;
    
         /** Rx生命周期管理 */
         private CompositeSubscription subscriptions;
    
         protected BaseMVPPresenter() {
             subscriptions = new CompositeSubscription();
         }
    
         /**
          * 綁定View
          *
          * @param view MVP View
          */
         public void onAttach(V view) {
             mView = view;
         }
    
         /**
          * 解綁MVP View
          */
         void onDetach() {
             mView = null;
         }
    
         /**
          * 添加到生命周期管理
          *
          * @param sub 訂閱者對象
          */
         protected void addSub(Subscription sub) {
             if (subscriptions == null) {
                 return;
             }
    
             if (sub != null) {
                 subscriptions.add(sub);
             }
         }
    
         /**
          * 解綁訂閱者
          */
         void unSubscribe() {
             if (subscriptions == null) {
                 return;
             }
    
             if (subscriptions.hasSubscriptions()) {
                 subscriptions.unsubscribe();
             }
         }
     }
    
  • 在BaseMVPPresenter中渐裂,我定義一些方法豺旬,包括綁定解綁View、Rx生命周期管理柒凉,這幾個(gè)方法是每個(gè)Presenter都會用到的族阅,并且使用了泛型來確定View和Module的類型。<b>注意:每次請求網(wǎng)絡(luò)都要調(diào)用addSub方法把Subscription對象添加到Rx生命周期膝捞。</b>

     /**
      * Presenter實(shí)現(xiàn)類
      *
      * @author 王杰
      */
     public class ImpPresenter extends BaseMVPPresenter<ImpView, ImpModule> {
    
         @Inject
         ImpPresenter() {
             super();
         }
    
         public void doSomething() {
    
             Subscription sub = mModule.doSomething(
                     data -> {
    
                         // 獲取數(shù)據(jù)成功
                         mView.notifyData(data);
    
                     }, throwable -> {
                         // 獲取數(shù)據(jù)失敗
                         mView.showToast("Net Error!");
                     });
             // 添加到生命周期
             addSub(sub);
         }
     }
    
  • 構(gòu)造方法調(diào)用父類構(gòu)造方法坦刀,多個(gè)Module也可以在這里初始化。

  • <b>構(gòu)造方法使用@Inject注解蔬咬, 使用Dagger2</b>

     /**
      * Module實(shí)現(xiàn)類
      *
      * @author 王杰
      */
     public class ImpModule {
    
         @Inject
         ImpModule () {
         }
    
         /**
          * 獲取評價(jià)最高電影
          */
         public Subscription doSomething(Action1<Bean> success, Action1<Throwable> throwable) {
             return RXClientGenerator.getInstance().createClient()
                     .doSomething()
                     .subscribeOn(Schedulers.io())
                     .observeOn(AndroidSchedulers.mainThread())
                     .subscribe(success, throwable);
         }
     }
    
  • 在Module中定義方法獲取數(shù)據(jù)等操作鲤遥,返回Subscription對象。

  • <b>由于BaseMVPPresenter中Module使用@Inject注解進(jìn)行初始化林艘,所有Module的構(gòu)造方法必須使用@Inject注解</b>

     /**
      * MVP View基類
      *
      * @author 王杰
      */
     public interface BaseMVPView {
    
         /**
          * Toast提示
          *
          * @param str 提示文本
          */
         void showToast(String str);
    
         /**
          * Toast提示
          *
          * @param strResId 提示文本id
          */
         void showToast(@StringRes int strResId);
     }
    
  • 在BaseMVPView中盖奈,定義了彈出Toast的方法,可以讓BaseActivity和BaseFragment實(shí)現(xiàn)這個(gè)接口狐援,并且實(shí)現(xiàn)這兩個(gè)方法卜朗,這樣的話,在Activity實(shí)現(xiàn)View接口的時(shí)候就不用重寫也能完成相關(guān)功能咕村。當(dāng)然了场钉,你可以把你項(xiàng)目中大多數(shù)界面需要用到的操作定義在這個(gè)接口里,并在Activity懈涛、Fragment的基類實(shí)現(xiàn)逛万。

  • 而關(guān)于Module則是獲取數(shù)據(jù)保存數(shù)據(jù)等操作,暫時(shí)沒有發(fā)現(xiàn)有共用的功能批钠,所以沒有封裝宇植。

進(jìn)一步封裝


  • MVP的基類都定義好了,那么接下來就是在各個(gè)界面中的封裝了埋心,對于MVP指郁,在Activity中和在Fragment中基本上是一致的,那么接下來拷呆,我就用BaseActivity舉例闲坎。

     /**
      * Activity基類
      *
      * @author 王杰
      */
     public abstract class BaseActivity<P extends BaseMVPPresenter> extends AppCompatActivity
             implements BaseMVPView {
    
         /** Presenter對象 */
         @Inject
         protected P presenter;
    
         @Override
         protected void onDestroy() {
             super.onDestroy();
    
             // Rx生命周期管理
             if (presenter != null) {
                 presenter.onDetach();
                 presenter.unSubscribe();
             }
         }
    
         @Override
         public void showToast(String str) {
             Toast.makeText(mContext, str, Toast.LENGTH_SHORT).show();
         }
    
         @Override
         public void showToast(@StringRes int strResId) {
             Toast.makeText(mContext, strResId, Toast.LENGTH_SHORT).show();
         }
     }
    
  • 使用泛型確定Presenter的類型,實(shí)現(xiàn)BaseMVPView茬斧,并且實(shí)現(xiàn)其中定義的方法腰懂。在界面銷毀時(shí),解綁View项秉,結(jié)束Rx生命周期绣溜。

總結(jié)


  • 項(xiàng)目中的MVP大概就是這樣了,實(shí)際上關(guān)于Presenter以及Module都可以向上抽取成接口娄蔼,使用者持有接口調(diào)用方法怖喻。但是由于項(xiàng)目中使用了Dagger2依賴注入底哗,無法將接口初始化為實(shí)現(xiàn)類,而且那樣做需要新建的類又太多了锚沸,所以并沒有抽取艘虎。
  • 這里的Presenter對象、Module對象咒吐,我都用到了Dagger2依賴注入,創(chuàng)建后會自動初始化属划。
  • 對Dagger2 不了解的朋友可以看我的上一篇文章 Android項(xiàng)目基本架構(gòu)(二) Dagger2
  • 項(xiàng)目Github地址
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末恬叹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子同眯,更是在濱河造成了極大的恐慌绽昼,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件须蜗,死亡現(xiàn)場離奇詭異硅确,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)明肮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進(jìn)店門菱农,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人柿估,你說我怎么就攤上這事循未。” “怎么了秫舌?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵的妖,是天一觀的道長。 經(jīng)常有香客問我足陨,道長嫂粟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任墨缘,我火速辦了婚禮星虹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘镊讼。我一直安慰自己搁凸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布狠毯。 她就那樣靜靜地躺著护糖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嚼松。 梳的紋絲不亂的頭發(fā)上嫡良,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天锰扶,我揣著相機(jī)與錄音,去河邊找鬼寝受。 笑死坷牛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的很澄。 我是一名探鬼主播京闰,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼甩苛!你這毒婦竟也來了蹂楣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤讯蒲,失蹤者是張志新(化名)和其女友劉穎痊土,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體墨林,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赁酝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了旭等。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片酌呆。...
    茶點(diǎn)故事閱讀 38,650評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖搔耕,靈堂內(nèi)的尸體忽然破棺而出肪笋,到底是詐尸還是另有隱情,我是刑警寧澤度迂,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布藤乙,位于F島的核電站,受9級特大地震影響惭墓,放射性物質(zhì)發(fā)生泄漏坛梁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一腊凶、第九天 我趴在偏房一處隱蔽的房頂上張望划咐。 院中可真熱鬧,春花似錦钧萍、人聲如沸褐缠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽队魏。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間胡桨,已是汗流浹背官帘。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留昧谊,地道東北人刽虹。 一個(gè)月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像呢诬,于是被迫代替她去往敵國和親涌哲。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內(nèi)容