Android 搭建MVP+Retrofit+RxJava網(wǎng)絡(luò)請求框架(二)

上一篇中簡單介紹了mvp的概念和retrofit的基本使用视搏,本篇主要是將rxjava和retrofit結(jié)合起來使用珍剑,并搭建mvp+rxajva+retrofit的demo;沒有rxjava和retrofit基礎(chǔ)的坤按,建議先去看上一篇:
Android 搭建MVP+Retrofit+RxJava網(wǎng)絡(luò)請求框架(一)

下面我們來看一下RxJava和retrofit的結(jié)合使用弃衍,為了使Rxjava與retrofit結(jié)合,我們需要在Retrofit對象建立的時候添加一句代碼:

addCallAdapterFactory(RxJava2CallAdapterFactory.create())

當(dāng)然你還需要在build.gradle文件中添加如下依賴:

compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'

本篇中所用的是rxjava2,完整的代碼如下:

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.douban.com/v2/")
        .addConverterFactory(GsonConverterFactory.create(new 
         GsonBuilder().create()))
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//支持RxJava
        .build();

然后我們還需要修改RetrofitService 中的代碼:

public interface RetrofitService {
    @GET("book/search")
    Observable<Book> getSearchBook(@Query("q") String name,
                                    @Query("tag") String tag, @Query("start") int start,
                                    @Query("count") int count);

可以看到燎孟,在原來的RetrofitService 中我們把getSearchBook方法返回的類型Call改為了Observable禽作,也就是被觀察者。其他都沒變揩页。然后就是創(chuàng)建RetrofitService 實體類:

RetrofitService service = retrofit.create(RetrofitService.class);
和上面一樣旷偿,創(chuàng)建完RetrofitService ,就可以調(diào)用里面的方法了:

Observable<Book> observable = service.getSearchBook("人間失格", null, 0, 1);
其實這一步爆侣,就是創(chuàng)建了一個rxjava中observable萍程,即被觀察者,有了被觀察者,就需要一個觀察者兔仰,且訂閱它:

observable.subscribeOn(Schedulers.io())//請求數(shù)據(jù)的事件發(fā)生在io線程
          .observeOn(AndroidSchedulers.mainThread())//請求完成后在主線程更顯UI
          .subscribe(new DisposableObserver<Book>() {//訂閱
              @Override
              public void onComplete() {
                  //所有事件都完成茫负,可以做些操作。乎赴。忍法。
              }
              @Override
              public void onError(Throwable e) {
                  e.printStackTrace(); //請求過程中發(fā)生錯誤
              }
              @Override
              public void onNext(Book book) {//這里的book就是我們請求接口返回的實體類    
              }
           }

在上面中我們可以看到,事件的消費(fèi)在Android主線程榕吼,所以我們還要在build.gradle中添加如下依賴:

compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

這樣我們就引入了RxAndroid饿序,RxAndroid其實就是對RxJava的擴(kuò)展。比如上面這個Android主線程在RxJava中就沒有羹蚣,因此要使用的話就必須得引用RxAndroid原探。

實踐

接下來我們就看看,在一個項目中上面三者是如何配合的度宦。我們打開Android Studio踢匣,新建一個項目取名為MVPSample。這個demo的功能也很簡單戈抄,就是點擊按鈕調(diào)用上面的那個測試接口离唬,將請求下來書的信息顯示在屏幕上。首先我們來看一下這個工程的目錄結(jié)構(gòu):

項目結(jié)構(gòu)圖.png

我們可以看到划鸽,在項目的包名下输莺,我們建了主要的文件夾:bean戚哎、data、presenter,ui;分別對應(yīng)不同的功能嫂用。其中app文件夾中可以建一個Application類型凳,用于設(shè)置應(yīng)用全局的一些屬性驶社,這里為了使項目更加簡單就沒有添加嗦董;然后,我們再來看看ui文件夾下芽腾,這個文件夾下主要放一些關(guān)于界面的東西往弓。在里面我們又建了三個文件夾:activity疏唾、adapter、fragment函似,我想看名字你就清楚里面要放什么了槐脏。RetrofitHelper和APiService。RetrofitHelper主要用于Retrofit的初始化:

public class RetrofitHelper {

    private Context mCntext;

    OkHttpClient client = new OkHttpClient();
    GsonConverterFactory factory = GsonConverterFactory.create(new GsonBuilder().create());
    private static RetrofitHelper instance = null;
    private Retrofit mRetrofit = null;
    public static RetrofitHelper getInstance(Context context){
        if (instance == null){
            instance = new RetrofitHelper(context);
        }
        return instance;
    }
    private RetrofitHelper(Context mContext){
        mCntext = mContext;
        init();
    }

    private void init() {
        resetApp();
    }

    private void resetApp() {
        mRetrofit = new Retrofit.Builder()
                .baseUrl(ApiService.BASE_URL)
                .client(client)
                .addConverterFactory(factory)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
    }
    public ApiService getServer(){
        return mRetrofit.create(ApiService.class);
    }
}

代碼并不復(fù)雜撇寞,其中resetApp方法顿天,就是前面介紹的Retrofit的創(chuàng)建,getServer方法就是為了獲取ApiService接口類的實例化蔑担。然后定義了一個靜態(tài)方法getInstance用于獲取自身RetrofitHelper的實例化牌废,并且只會實例化一次。

在正式的項目中model,view,presenter都需要根據(jù)需求創(chuàng)建對應(yīng)的BaseView,BaseModel,BasePresenter;當(dāng)前demo中只是簡單創(chuàng)建啤握,后再后續(xù)封裝中繼續(xù)完善框架畔规。
先創(chuàng)建一個BookInfoContract

public interface BookInfoContract {
    interface IView extends BaseView {

        void showResult(String  msg);

//        void onRequestPermissionSuccess();
//
//        void onRequestPermissionSError();
    }

     interface IBookModel {

        Observable<Book> getBookMsg(String name,String tag,int start,int count);

    }

}

這是采用google官方demo的寫法,將相關(guān)的view和model接口寫到一個協(xié)議接口類中恨统。方便查找和管理叁扫,每一個view,model畜埋,presenter都有對應(yīng)的接口類相對應(yīng)莫绣,這種寫法雖然類增加了,但是便于解耦悠鞍,改動和維護(hù)方便对室;
具體實現(xiàn)步驟如下:

  1. 創(chuàng)建BookInfoModel,實現(xiàn)接口咖祭,并重寫獲取數(shù)據(jù)的方法
public class BookInfoModel implements BookInfoContract.IBookModel {

    private ApiService mApiService;

    public BookInfoModel(ApiService mApiService) {
        this.mApiService = mApiService;
    }

    @Override
    public Observable<Book> getBookMsg(String name, String tag, int start, int count) {
        return mApiService.getSearchBooks(name, tag, start, count);
    }
}

2.創(chuàng)建presenter,通過構(gòu)造傳入需要關(guān)聯(lián)的view,并初始化model;在getMsg()方法中掩宜,通過model中
getBookMsg()方法返回的被觀察者進(jìn)入線程切換和事件訂閱;在訂閱回調(diào)中么翰,調(diào)用view的方法對請求的結(jié)果進(jìn)行處理牺汤;一般presenter持有view的引用,增加了耦合性浩嫌,后面會進(jìn)行優(yōu)化處理

public class BookPresenter {

    private BookInfoContract.IView mView;
    private BookInfoModel bookInfoModel;
    private Book mBook;

    public BookPresenter(BookInfoContract.IView mView) {
        this.mView = mView;
        bookInfoModel = new BookInfoModel(RetrofitHelper.getInstance((Context) mView).getServer());
    }

    //獲取數(shù)據(jù)
    public void getMsg(String name, String tag, int start, int count) {
        bookInfoModel.getBookMsg(name, tag, start, count)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Book>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Book value) {
                        mBook = value;
                    }

                    @Override
                    public void onError(Throwable e) {
                        e.printStackTrace();
                        mView.showError("請求失敗");
                    }

                    @Override
                    public void onComplete() {
                        if (mView != null) {
                            mView.showResult(mBook.toString());
                        }
                    }
                });

    }
}

3.在mainActivity中實現(xiàn)接口 BookInfoContract.IView檐迟;通過注解初始化控件(在onDestroy中進(jìn)行接觸注解)并獲取初始化presenter,在控件監(jiān)聽事件中补胚。調(diào)用presenter的方法獲取數(shù)據(jù);

經(jīng)過以上幾步基本完成了mvp+rxjava+retrofit的框架搭建
項目地址:https://github.com/cruiseliang/MvpSample

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末追迟,一起剝皮案震驚了整個濱河市溶其,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌敦间,老刑警劉巖瓶逃,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異廓块,居然都是意外死亡金闽,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門剿骨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人埠褪,你說我怎么就攤上這事浓利。” “怎么了钞速?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵贷掖,是天一觀的道長。 經(jīng)常有香客問我渴语,道長苹威,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任驾凶,我火速辦了婚禮牙甫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘调违。我一直安慰自己窟哺,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布技肩。 她就那樣靜靜地躺著且轨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪虚婿。 梳的紋絲不亂的頭發(fā)上旋奢,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天,我揣著相機(jī)與錄音然痊,去河邊找鬼至朗。 笑死,一個胖子當(dāng)著我的面吹牛剧浸,可吹牛的內(nèi)容都是我干的爽丹。 我是一名探鬼主播筑煮,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼粤蝎!你這毒婦竟也來了真仲?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤初澎,失蹤者是張志新(化名)和其女友劉穎秸应,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體碑宴,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡软啼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了延柠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片祸挪。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖贞间,靈堂內(nèi)的尸體忽然破棺而出贿条,到底是詐尸還是另有隱情,我是刑警寧澤增热,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布整以,位于F島的核電站,受9級特大地震影響峻仇,放射性物質(zhì)發(fā)生泄漏公黑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一摄咆、第九天 我趴在偏房一處隱蔽的房頂上張望凡蚜。 院中可真熱鬧,春花似錦吭从、人聲如沸番刊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽芹务。三九已至,卻和暖如春鸭廷,著一層夾襖步出監(jiān)牢的瞬間枣抱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工辆床, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留佳晶,地道東北人。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓讼载,卻偏偏與公主長得像轿秧,于是被迫代替她去往敵國和親中跌。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,086評論 2 355

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