Retrofit2-RxJava-Dagger2-MVP完美封裝

如果對 Retrofit2+RxJava 封裝還不是很了解的話
可以參考下:
http://www.reibang.com/p/17e3e3102c1f
如果對Dagger2 還不是很了解,可以參考下:
http://www.reibang.com/p/cd2c1c9f68d4
如果對mvp還不是很了解,可以自己百度下,很多的,我就不貼出了.
下面我簡單講述下:
請先看下目錄結構:

com
└── javalong
└── rrdm
├── activity
│   ├── component
│   │   ├── LoginActivityComponent.java
│   │   └── MainActivityComponent.java
│   ├── iview
│   │   ├── ILoginView.java
│   │   └── IMainView.java
│   ├── LoginActivity.java
│   ├── MainActivity.java
│   ├── module
│   │   ├── LoginActivityModule.java
│   │   └── MainActivityModule.java
│   └── presenter
│       ├── LoginPresenter.java
│       └── MainPresenter.java
├── app
│   ├── annotation
│   │   └── ActivityScope.java
│   ├── AppBaseActivity.java
│   ├── AppBaseApplication.java
│   ├── component
│   │   └── AppComponent.java
│   ├── iview
│   │   └── MvpView.java
│   ├── module
│   │   └── AppModule.java
│   └── presenter
│       └── AppPresenter.java
└── retrofit
├── ResponseMessageBean.java
├── RetrofitHelper.java
├── ServerApi.java
├── TWGsonConverterFactory.java
├── TWGsonRequestBodyConverter.java
├── TWGsonResponseBodyConverter.java
└── TWJavaCallAdapterFactory.java

這里我就不對mvp,dagger2和Retrofit2+Rxjava過多介紹了.這里就介紹下具體的封裝.
我這里是一個Presenter和一個Activity(View)相互對應,所以我讓Presenter直接在基類中注入.對其進行統(tǒng)一管理:
AppPresenter.Java:

/** 
 * Created by javalong on 16-12-27. 
 * presenter基類 
 */  
public abstract class AppPresenter<V extends MvpView>{  
    @Inject  
    protected V mvpView;  
  
    public AppPresenter(V mvpView) {  
        this.mvpView = mvpView;  
    }  
  
    public abstract void attach();  
    public abstract void detach();  
}  

AppBaseActivity.java--->所有Activity的基類,對presenter進行統(tǒng)一處理.

/** 
 * Created by javalong on 16-12-27. 
 */  
  
public abstract class AppBaseActivity<T extends AppPresenter> extends AppCompatActivity {  
    @Inject  
    protected T mPresenter;  
  
    @Override  
    protected void onCreate(@Nullable Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        initInjects();  
        mPresenter.attach();  
    }  
  
    protected abstract void initInjects();  
  
    @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        mPresenter.detach();  
    }  
  
    protected AppComponent getAppComponent(){  
        return AppBaseApplication.getInstance().getAppComponent();  
    }  
}  

AppBaseActivity中引用了AppComponent.這個需要在AppBaseApplication進行初始化.Component是dagger2依賴注入的基礎.

AppBaseApplication.java

/** 
 * Created by javalong on 16-12-27. 
 */  
  
public class AppBaseApplication extends Application {  
  
    private static AppBaseApplication instance;  
  
    public static AppBaseApplication getInstance() {  
        return instance;  
    }  
  
    AppComponent appComponent;  
  
    public AppComponent getAppComponent() {  
        return appComponent;  
    }  
  
    @Override  
    public void onCreate() {  
        super.onCreate();  
        instance = this;  
        if (appComponent == null) {  
            appComponent = DaggerAppComponent.builder().appModule(new AppModule(this)).build();  
        }  
    }  
}  

如果不熟悉Dagger2的童鞋,可能會發(fā)現(xiàn)沒有DaggerAppComponent這個類,不要慌,請'Make Project'編譯下項目.DaggerAppComponent會自動生成.DaggerAppComponent其實是根據(jù)我們寫的AppComponent接口生成的一個類,下面我們先看下AppComponent.

@Singleton  
@Component(modules = AppModule.class)  
public interface AppComponent {  
    Context getContext();  
    ServerApi getServerApi();  
}  

AppComponent這個接口其實很簡單.這里記得要加上@Scope注解(@Singleton是@Scope的一種)使Component和Module中provide出來的對象聯(lián)系起來.
關于@Scope注解的含義我這里就不過多介紹了,大家可以參考我上面推薦的文章.寫的很不錯.
接下來看下AppModule中提供了哪些依賴

@Module  
public class AppModule {  
  
    private Context mContext;  
  
    public AppModule(Context context) {  
        this.mContext = context;  
    }  
  
    @Provides @Singleton  
    Context provideContext(){  
        return mContext;  
    }  
  
    @Provides @Singleton  
    ServerApi provideServerApi(Context context){  
        RetrofitHelper.init(context);  
        return RetrofitHelper.getApi();  
    }  
  
}  

這里的@Singleton 和前面AppComponent的@Singleton 相互連接,讓我們造成了單例的假象.其實@Singleton并沒有單例的作用,是因為
和AppComponent一起使用,AppComponent只創(chuàng)建了一次,所以產(chǎn)生'單例'這個現(xiàn)象.(我這里又重復得說了一邊,汗~~)
AppComponent和AppModule請根據(jù)自己項目的詳細情況來進行封裝,由于我這個demo比較簡單,所以只@Provides 了2個對象出來.

下面我來詳細介紹下Activity和Presenter之間的封裝.
首先我這里先說明下,我這里的一個Activity,對應著1個view,1個presenter,1個component,1個module.
可能封裝的不是很好,沒有領悟到mvp的精髓,但是對我來說更加清晰.
MainActivity.java

public class MainActivity extends AppBaseActivity<MainPresenter> implements IMainView{  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        mPresenter.test();  
    }  
  
    @Override  
    protected void initInjects() {  
        DaggerMainActivityComponent.builder()  
                .appComponent(getAppComponent())  
                .mainActivityModule(new MainActivityModule(this))  
                .build()  
                .inject(this);  
    }  
  
  
    @Override  
    public void showMainMessage() {  
        ((TextView)findViewById(R.id.tv_test))  
                .setText("你好 dagger");  
        findViewById(R.id.bt_login)  
        .setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                LoginActivity.start(MainActivity.this);  
                MainActivity.this.finish();  
            }  
        });  
    }  
}  

MainActivity必須繼承AppBaseActivity,然后傳入泛型,即對應的Presenter的類型.在initInjects中必須完成Dagger2的注入操作,因為在AppBaseActivity中的Presenter需要
注入,如果不注入,在基類中調(diào)用mPresenter.attach會出錯.
當你使用Dagger2的時候,其實很明顯會暴露他的一個缺點,必須要編譯后,才能產(chǎn)生對應的Dagger**Component.當然相對于他的好處來講,這點還是可以忍受的.
前面提到了必須要對基類中的Presenter進行注入,那么到底注入的是什么呢?這里我以MainPresenter為例.

public class MainPresenter extends AppPresenter<IMainView>{  
  
    @Inject  
    public MainPresenter(IMainView mvpView) {  
        super(mvpView);  
    }  
  
    @Override  
    public void attach() {  
  
    }  
  
    @Override  
    public void detach() {  
  
    }  
  
    public void test() {  
        mvpView.showMainMessage();  
    }  
}  

MainActivityModule.java

@Module  
public class MainActivityModule  {  
  
    private IMainView mainView;  
  
    public MainActivityModule(IMainView mainView) {  
        this.mainView = mainView;  
    }  
  
    @Provides @ActivityScope IMainView provideIMainView(){  
        return mainView;  
    }  
  
    /** 
     * 這種方式,和直接在MainPresenter構造方法上添加@Inject是一樣的 
     * 二選一即可. 
     */  
//    @Provides @ActivityScope MainPresenter provideMainPresenter(IMainView mainView){  
//        return new MainPresenter(mainView);  
//    }  
}  

看注釋,這里有2種方式可以完成MainPresenter的注入,一種是直接在MainPreenter的構造方法上加上@Inject,一種是在對應的Module中使用
@Provides 把MainPresenter提供出來. 至于@ActivityScope其實是和前面@Scope一樣的,我這里就不過多介紹了.
最關鍵的一步:
MainActivityComponent.java

@ActivityScope  
@Component(dependencies = AppComponent.class,modules = MainActivityModule.class)  
public interface MainActivityComponent{  
    /** 
     * @param mainView 
     * 這里必須使用MainActivity,不能使用IMain接口 
     * 否則會造成@Inject注入失敗 
     */  
    void inject(MainActivity mainView);  
} 

必須在對應的Component提供注入方法(名字不一定叫inject).
MainActivity.java 部分代碼

@Override  
   protected void initInjects() {  
       DaggerMainActivityComponent.builder()  
               .appComponent(getAppComponent())  
               .mainActivityModule(new MainActivityModule(this))  
               .build()  
               .inject(this);  
   }  

這樣才完成了注入.
DaggerMainActivityComponent中會先對AppBaseActivity進行注入,然后再對MainActivity進行注入.
這里我簡單的講述了封裝,如果還有什么不懂的地方可以再交流~~~github: https://github.com/javalong/Retrofit2-RxJava-Dagger2-MVP

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末议慰,一起剝皮案震驚了整個濱河市秉扑,隨后出現(xiàn)的幾起案子杈曲,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異伺通,居然都是意外死亡,警方通過查閱死者的電腦和手機逢享,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門罐监,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人瞒爬,你說我怎么就攤上這事弓柱。” “怎么了侧但?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵矢空,是天一觀的道長。 經(jīng)常有香客問我禀横,道長屁药,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任柏锄,我火速辦了婚禮酿箭,結果婚禮上复亏,老公的妹妹穿的比我還像新娘。我一直安慰自己缭嫡,他們只是感情好缔御,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著妇蛀,像睡著了一般耕突。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上评架,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天有勾,我揣著相機與錄音,去河邊找鬼古程。 笑死,一個胖子當著我的面吹牛喊崖,可吹牛的內(nèi)容都是我干的挣磨。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼荤懂,長吁一口氣:“原來是場噩夢啊……” “哼茁裙!你這毒婦竟也來了?” 一聲冷哼從身側響起节仿,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤晤锥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后廊宪,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體矾瘾,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年箭启,在試婚紗的時候發(fā)現(xiàn)自己被綠了壕翩。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡傅寡,死狀恐怖放妈,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情荐操,我是刑警寧澤芜抒,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站托启,受9級特大地震影響宅倒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜驾中,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一唉堪、第九天 我趴在偏房一處隱蔽的房頂上張望模聋。 院中可真熱鬧,春花似錦唠亚、人聲如沸链方。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽祟蚀。三九已至,卻和暖如春割卖,著一層夾襖步出監(jiān)牢的瞬間前酿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工鹏溯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留罢维,地道東北人。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓丙挽,卻偏偏與公主長得像肺孵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子颜阐,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

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