(三)安卓框架搭建之MVP+Retrofit+RxJava基礎(chǔ)

上一篇,算是完成了準(zhǔn)備工作爆哑,那么這篇就來說說MVP和RxJava的封裝了面哼。首先看看接口返回數(shù)據(jù)的格式:

{
"code" : 1,
"message" : "請求成功!" ,
"data" : {
    "name": "張三",
    "age": 3
  }
}

code乔妈、message、data標(biāo)準(zhǔn)的三大門神氓皱。一般是以這種格式返回數(shù)據(jù)路召。數(shù)據(jù)格式的統(tǒng)一利于封裝,以此數(shù)據(jù)格式為準(zhǔn)的實體基類如下
在dataframework內(nèi)新建包model和BaseResponseBean類波材。

Paste_Image.png
package com.example.burro.demo.dataframework.model;

/**基類 泛型T為實體數(shù)據(jù)
 * Created by ex.zhong on 2017/9/23.
 */
public class BaseResponseBean<T> {
    private int code;
    private String message;
    private T data;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

由于后面的demo用到豆瓣的API股淡,很遺憾它的格式并非上述標(biāo)準(zhǔn)的格式。在項目中返回的數(shù)據(jù)用了繼承父類方式廷区,而非上面的泛型方式揣非,為了區(qū)分。新的父類名字我改為BaseResultBean躲因,上面的標(biāo)準(zhǔn)格式基類我仍舊保存到demo中早敬,如果更換的話,那也是分分鐘的事情大脉。后面案例和講解也將使用BaseResultBean搞监,其內(nèi)容如下:

package com.example.burro.demo.dataframework.model;

/**返回數(shù)據(jù)父類。子類可繼承
 * Created by ex.zhong on 2017/9/23.
 */
public class BaseResultBean {
    protected int code;
    protected String msg;
    public BaseResultBean() {
    }
    public BaseResultBean(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

當(dāng)然镰矿,項目中要根據(jù)實際數(shù)據(jù)為準(zhǔn)來調(diào)整調(diào)整字段琐驴、結(jié)構(gòu)等。沒有必要過于糾結(jié)數(shù)據(jù)格式問題秤标,換湯不換藥绝淡,道理是一樣的。

下面進行MVP相關(guān)內(nèi)容的講解苍姜!

依賴包引入:

項目的build.gradle增加如下appframework

        /*rx-android-java*/
        rxjava                : 'io.reactivex:rxjava:1.1.0',
        rxandroid             : 'io.reactivex:rxandroid:1.1.0',
        retrofit              : 'com.squareup.retrofit2:retrofit:2.0.2',
        converter_gson        : 'com.squareup.retrofit2:converter-gson:2.0.2',
        adapter_rxjava        : 'com.squareup.retrofit2:adapter-rxjava:2.0.2',
        //compile 'com.google.code.gson:gson:2.6.2'
        logging_interceptor   : 'com.squareup.okhttp3:logging-interceptor:3.3.0',
        spots_dialog          : 'com.github.d-max:spots-dialog:0.7@aar',

dataframework的build.gradle增加如下

    compile deps.rxjava
    compile deps.rxandroid
    compile deps.retrofit
    compile deps.converter_gson
    compile deps.adapter_rxjava
    compile deps.logging_interceptor
    compile deps.spots_dialog
    compile deps.annotation

BaseView

Paste_Image.png

寫之前需要在appframework下新建包mvp,mvp下新建三個包contract,presenter,view
在view下新建接口BaseView牢酵,Baseview接口內(nèi)的方法是頁面內(nèi)【Activity或者Fragment】需要執(zhí)行的通用方法。這里先定義一個 showError(BaseResultBean resultBean); 返回正確情況有很多種衙猪,在實現(xiàn)類中增加馍乙,若錯誤,我們要統(tǒng)一處理垫释。所以showError(BaseResultBean resultBean)方法是全局共有的丝格。

package com.example.burro.demo.appframework.mvp.view;

import com.example.burro.demo.dataframework.model.BaseResultBean;

/**View接口
 * Created by ex.zhong on 2017/9/23.
 */
public interface BaseView {
    void showError(BaseResultBean  resultBean);
}

BasePresenter

Presenter和View創(chuàng)建類似,
在presenter下新建IPresenter棵譬,IPresenter attachView(T view); void detachView();兩個方法是全局共有的

package com.example.burro.demo.appframework.mvp.presenter;

import com.example.burro.demo.appframework.mvp.view.BaseView;

/**Presenter接口
 * 注:在創(chuàng)建presenter時綁定显蝌,在頁面destroy()時解綁。
 * Created by ex.zhong on 2017/9/23.
 */
public interface IPresenter<T extends BaseView> {
    void attachView(T view);
    void detachView();
}

因為幾乎每個Presenter實現(xiàn)類里都要處理綁定和解綁事件订咸,所以我們要把這個處理過程提取出來曼尊,此處寫一個基類BasePresenter統(tǒng)一管理扭屁,在presenter下新建BasePresenter實現(xiàn)IPresenter

package com.example.burro.demo.appframework.mvp.presenter;

import com.example.burro.demo.appframework.mvp.view.BaseView;

/**
 * Presenter基類。目的是統(tǒng)一處理綁定和解綁
 * Created by ex.zhong on 2017/9/23.
 */
public class BasePresenter<T extends BaseView> implements IPresenter<T> {

    protected T mView;

    @Override
    public void attachView(T mView) {
        mView = mView;
    }

    @Override
    public void detachView() {
        mView = null;
    }

  //   public boolean isViewAttached() {
  //      return mView != null;
  //    }

  //    public void checkViewAttached() {
  //        if (!isViewAttached()) throw new  
  // MvpViewNotAttachedException();
  //  }
![Uploading 04_766476.png . . .]

  //   public static class  //MvpViewNotAttachedException extends //RuntimeException {
  //        public MvpViewNotAttachedException() {
  //           super("Please call   //Presenter.attachView(MvpView) before" +
  //                    " requesting data to the   //Presenter");
  //        }
  //    }
}

【備注:這里的checkViewAttached(),在rxJava未引入之前使用涩禀。目的是判斷頁面是否還存在料滥,若不存在則不執(zhí)行。rxJava中對此作了處理艾船。只需調(diào)用解綁方法即可葵腹。在此處稍作提及,后面我會直接刪掉此內(nèi)容】

稍后會寫一個測試類TestActivty結(jié)合豆瓣的API屿岂。來詳解mvp的使用践宴。在此之前先來封裝一下BaseActivity,因為一般都是在BaseActivity中進行Presenter和View的初始化綁定

BaseActivity

在appframework新建ui包,包內(nèi)新建BaseActivity抽象類

類中都是基本的要素爷怀,且注釋較為詳細(xì)阻肩,容易理解。其中有個別方法是為了和后面內(nèi)容對接运授,直接貼代碼:

package com.example.burro.demo.appframework.ui;

import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;

import com.example.burro.demo.appframework.BaseApplication;
import com.example.burro.demo.appframework.mvp.presenter.BasePresenter;
import com.example.burro.demo.appframework.mvp.view.BaseView;

import butterknife.ButterKnife;
import butterknife.Unbinder;

/**
 * BaseActivity Activity基類
 * butterKnife的綁定 初始方法的設(shè)定 presentet和view的綁定
 * Created by ex.zhong on 2017/9/23.
 */
public abstract class BaseActivity<T extends BasePresenter> extends AppCompatActivity implements BaseView,Toolbar.OnMenuItemClickListener {
    protected T mPresenter;
    protected Activity mContext;
    private Unbinder mUnbinder;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(initLayoutInflater());
        mUnbinder = ButterKnife.bind(this);
        mContext = this;
        createPresenter();
        if (mPresenter != null) mPresenter.attachView(this);
        BaseApplication.getInstance().addActivity(this);
        initParams();
        initViews();
    }
    protected abstract int initLayoutInflater(); //初始化布局

    protected abstract void initParams(); //初始化參數(shù)

    protected abstract void initViews();  //初始化控件

    protected abstract void createPresenter(); //創(chuàng)建presenter

    /**
     * @param toolbar toolbar 控件
     * @param title   標(biāo)題
     */
    protected void setToolBar(Toolbar toolbar, String title) {
        if (toolbar != null) {
            if (title != null) toolbar.setTitle(title);
            setSupportActionBar(toolbar);
            toolbar.setOnMenuItemClickListener(this);
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
            getSupportActionBar().setDisplayShowHomeEnabled(true);
            toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    onBackPressed();
                }
            });
        }
    }
    //toolbar右側(cè)menu點擊事件
    @Override
    public boolean onMenuItemClick(MenuItem item) {
        return false;
    }
      //統(tǒng)一處理錯誤信息
    public void handleError(BaseResultBean errResult) {
        if (errResult == null) return;
        if (this == null) return;
        //可以分門別類的處理 錯誤消息烤惊,如session過期,跳轉(zhuǎn)到登錄頁面吁朦。其他情況提示即可
        ToastUtils.showToast(mContext, errResult.getMsg());
    }
    
    @Override
    protected void onDestroy() {
        if (mPresenter != null) mPresenter.detachView();
        if (mUnbinder != null) mUnbinder.unbind();
        super.onDestroy();
    }
}

在biz新建測試類

新建內(nèi)容如下 biz/test/view/TestActivity柒室、biz/test/TestContract、biz/test/TestPresenterImpl

1.包內(nèi)新建TestActivity繼承BaseActivity.TestActivity

package com.example.burro.demo.appbiz.test.view;

import com.example.burro.demo.appbiz.R;
import com.example.burro.demo.appbiz.R2;
import com.example.burro.demo.appbiz.test.TestContract;
import com.example.burro.demo.appbiz.test.TestPresenterImpl;
import com.example.burro.demo.appframework.ui.BaseActivity;
import com.example.burro.demo.appframework.util.LogUtils;
import com.example.burro.demo.databiz.model.test.MovieListBean;
import com.example.burro.demo.dataframework.model.BaseResultBean;

import butterknife.OnClick;

/**測試頁面
 * Created by ex.zhong on 2017/9/23.
 */
public class TestActivity extends BaseActivity<TestPresenterImpl> implements TestContract.View{
    @Override
    protected int initLayoutInflater() {
        return R.layout.activity_test;
    }
    @Override
    protected void initParams() {
    }
    @Override
    protected void initViews() {
    }

    @Override
    protected void createPresenter() {
        mPresenter = new TestPresenterImpl();
    }

    @Override
    public void showError(BaseResultBean resultBean) {
         //錯誤處理
        handleError(resultBean);
    }

    @Override
    public void setMovieListData(MovieListBean bean) {
        LogUtils.i("TAG",bean==null?"":bean.toString());
    }
    @OnClick(R2.id.btnTest)
    public void getMovieListData(){
        mPresenter.getMovieListData(1,15);
    }
}

這里的showError(),是BasePresenter中的回調(diào)方法逗宜,用來統(tǒng)一處理錯誤情況雄右,若頁面有RecycalView并正在刷新的情況,也可在此處結(jié)束刷新纺讲。因為每個頁面都會showError()擂仍,所以我們需要在BaseActivity里增加統(tǒng)一處理的方法handleError(resultBean),內(nèi)容如下:

    //統(tǒng)一處理錯誤信息
    public void handleError(BaseResultBean errResult) {
        if (errResult == null) return;
        if (this == null) return;
        //可以分門別類的處理 錯誤消息熬甚,如session過期逢渔,跳轉(zhuǎn)到登錄頁面。其他情況提示即可
        ToastUtils.showToast(mContext, errResult.getMsg());
    }

值得強調(diào)的是则涯,增加錯誤結(jié)果統(tǒng)一處理很有必要复局,也很少有人注意這點,我們后面網(wǎng)絡(luò)請求錯誤結(jié)果的返回也會與此對接粟判。此處默認(rèn)是給出Toast提示信息,當(dāng)然還有很多其他操作峦剔,正如注釋所說:如果errResult的code是session過期的標(biāo)識档礁,那么我們給出提示的同時也會跳轉(zhuǎn)至登錄頁面等等。

2.TestContract:

Contract:d單詞意思為契約吝沫、協(xié)議呻澜。TestContract即協(xié)議類递礼,定制mvp各層接口和實現(xiàn)方法。說白了羹幸,就是把v層和p層需要實現(xiàn)的方法統(tǒng)一在一塊脊髓,方便管理,也起到了解耦作用栅受。

package com.example.burro.demo.appbiz.test;

import com.example.burro.demo.appframework.mvp.presenter.IPresenter;
import com.example.burro.demo.appframework.mvp.view.BaseView;
import com.example.burro.demo.databiz.model.test.MovieListBean;

/**協(xié)議類将硝,定制mvp各層接口和實現(xiàn)方法
 * Contract:d單詞意思為契約 協(xié)議
 * 接口View內(nèi) 定義實現(xiàn)view內(nèi)所需方法
 * 接口Presenter 定義實現(xiàn)presenter內(nèi)所需的方法
 * Created by ex.zhong on 2017/9/23.
 */
public class TestContract {
    public interface View extends BaseView {
        void setMovieListData(MovieListBean bean);
    }

    public interface Presenter extends IPresenter<View> {
        void getMovieListData(int start,int count);
    }
}

3.TestPresenterImpl:

TestPresenterImpl繼承自BasePresenter,初級版本如下:

package com.example.burro.demo.appbiz.test;

import com.example.burro.demo.appframework.mvp.presenter.BasePresenter;
import com.example.burro.demo.appbiz.test.TestContract.*;
import com.example.burro.demo.appframework.util.LogUtils;
import com.example.burro.demo.appframework.util.StringUtils;
import com.example.burro.demo.databiz.model.test.MovieListBean;
import com.example.burro.demo.databiz.service.ApiService;
import com.example.burro.demo.dataframework.http.HttpConfig;

import java.util.HashMap;

import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

/**測試presenter
 * Created by ex.zhong on 2017/9/23.
 */
public class TestPresenterImpl extends BasePresenter<View> implements Presenter {

    @Override
    public void getMovieListData(int start, int count) {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(HttpConfig.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        ApiService movieService = retrofit.create(ApiService.class);
        HashMap<String,String> map=new HashMap<>();
        map.put("start", StringUtils.getString(start));
        map.put("count",StringUtils.getString(count));
        movieService.getMovieListData(map)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<MovieListBean>() {
                    @Override
                    public void onStart() {
                        //請求開始
                        LogUtils.i("TestPresenterImpl","onStart()");
                    }
                    @Override
                    public void onCompleted() {
                       // //請求完成
                        LogUtils.i("TestPresenterImpl","onCompleted()");
                    }
                    @Override
                    public void onError(Throwable e) {
                        // //請求異常
                        LogUtils.i("TestPresenterImpl","onError()");
                    }
                    @Override
                    public void onNext(MovieListBean movieListBean) {
                        // //請求OK屏镊,執(zhí)行
                        LogUtils.i("TestPresenterImpl","onNext()");
                        mView.setMovieListData(movieListBean);
                    }
                });
    }
}

文中用到的豆瓣電影TOP250的URL為:http://api.douban.com/v2/movie/top250?start=1&count=15

其他幾個主要輔助的類或資源分別為如下:

布局文件activity_test.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.burro.demo.appbiz.test.view.TestActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appBarLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />
    </android.support.design.widget.AppBarLayout>
    <Button
        android:id="@+id/btnTest"
        android:layout_below="@id/appBarLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="請求數(shù)據(jù)"
        />

</RelativeLayout>

其中AppTheme.PopupOver,AppTheme.AppBarOverlay等是toolbar相關(guān)的樣式資源依疼,請到demo中查看,此處不一一列出

ApiService接口類 databiz/service/ApiService:

package com.example.burro.demo.databiz.service;


import com.example.burro.demo.databiz.model.test.MovieListBean;

import java.util.HashMap;
import java.util.Map;

import retrofit2.http.GET;
import retrofit2.http.Path;
import retrofit2.http.Query;
import retrofit2.http.QueryMap;
import rx.Observable;

/**
 *  存放訪問網(wǎng)絡(luò)的方法
 * Created by ex.zhong on 2017/9/24.
 */
public interface ApiService {
    public static final String URL_MOVIELIST="/v2/movie/top250"; //豆瓣電影top250
    @GET(URL_MOVIELIST)
    Observable<MovieListBean> getMovieListData(@QueryMap HashMap<String,String> count);
}

網(wǎng)絡(luò)配置類 dataframework/http/HttpConfig :

package com.example.burro.demo.dataframework.http;

/**
 * Created by ex.zhong on 2017/9/24.
 *放置網(wǎng)絡(luò)相關(guān)配置數(shù)據(jù)而芥,如IP/端口等
 */
public class HttpConfig {
    public final static String BASE_URL="http://api.douban.com";
}

電影列表實體類 databiz/model/test/MovieListBean :

package com.example.burro.demo.databiz.model.test;

import com.example.burro.demo.dataframework.model.BaseResultBean;

import java.util.List;

/**豆瓣電影列表
 * Created by ex.zhong on 2017/9/24.
 */

public class MovieListBean extends BaseResultBean{

    public List<SubjectsBean> subjects;

    public static class SubjectsBean {
        /**
         * rating : {"max":10,"average":9.6,"stars":"50","min":0}
         * genres : ["犯罪","劇情"]
         * title : 肖申克的救贖
         * casts : [{"alt":"https://movie.douban.com/celebrity/1054521/","avatars":{"small":"https://img3.doubanio.com/img/celebrity/small/17525.jpg","large":"https://img3.doubanio.com/img/celebrity/large/17525.jpg","medium":"https://img3.doubanio.com/img/celebrity/medium/17525.jpg"},"name":"蒂姆·羅賓斯","id":"1054521"},{"alt":"https://movie.douban.com/celebrity/1054534/","avatars":{"small":"https://img3.doubanio.com/img/celebrity/small/34642.jpg","large":"https://img3.doubanio.com/img/celebrity/large/34642.jpg","medium":"https://img3.doubanio.com/img/celebrity/medium/34642.jpg"},"name":"摩根·弗里曼","id":"1054534"},{"alt":"https://movie.douban.com/celebrity/1041179/","avatars":{"small":"https://img1.doubanio.com/img/celebrity/small/5837.jpg","large":"https://img1.doubanio.com/img/celebrity/large/5837.jpg","medium":"https://img1.doubanio.com/img/celebrity/medium/5837.jpg"},"name":"鮑勃·岡頓","id":"1041179"}]
         * collect_count : 1107705
         * original_title : The Shawshank Redemption
         * subtype : movie
         * directors : [{"alt":"https://movie.douban.com/celebrity/1047973/","avatars":{"small":"https://img3.doubanio.com/img/celebrity/small/230.jpg","large":"https://img3.doubanio.com/img/celebrity/large/230.jpg","medium":"https://img3.doubanio.com/img/celebrity/medium/230.jpg"},"name":"弗蘭克·德拉邦特","id":"1047973"}]
         * year : 1994
         * images : {"small":"https://img3.doubanio.com/view/movie_poster_cover/ipst/public/p480747492.webp","large":"https://img3.doubanio.com/view/movie_poster_cover/lpst/public/p480747492.webp","medium":"https://img3.doubanio.com/view/movie_poster_cover/spst/public/p480747492.webp"}
         * alt : https://movie.douban.com/subject/1292052/
         * id : 1292052
         */

        public RatingBean rating;
        public String title;
        public int collect_count;
        public String original_title;
        public String subtype;
        public String year;
        public ImagesBean images;
        public String alt;
        public String id;
        public List<String> genres;
        public List<CastsBean> casts;
        public List<DirectorsBean> directors;

        public static class RatingBean {
            /**
             * max : 10
             * average : 9.6
             * stars : 50
             * min : 0
             */

            public int max;
            public double average;
            public String stars;
            public int min;
        }

        public static class ImagesBean {
            /**
             * small : https://img3.doubanio.com/view/movie_poster_cover/ipst/public/p480747492.webp
             * large : https://img3.doubanio.com/view/movie_poster_cover/lpst/public/p480747492.webp
             * medium : https://img3.doubanio.com/view/movie_poster_cover/spst/public/p480747492.webp
             */

            public String small;
            public String large;
            public String medium;
        }

        public static class CastsBean {
            /**
             * alt : https://movie.douban.com/celebrity/1054521/
             * avatars : {"small":"https://img3.doubanio.com/img/celebrity/small/17525.jpg","large":"https://img3.doubanio.com/img/celebrity/large/17525.jpg","medium":"https://img3.doubanio.com/img/celebrity/medium/17525.jpg"}
             * name : 蒂姆·羅賓斯
             * id : 1054521
             */

            public String alt;
            public AvatarsBean avatars;
            public String name;
            public String id;

            public static class AvatarsBean {
                /**
                 * small : https://img3.doubanio.com/img/celebrity/small/17525.jpg
                 * large : https://img3.doubanio.com/img/celebrity/large/17525.jpg
                 * medium : https://img3.doubanio.com/img/celebrity/medium/17525.jpg
                 */

                public String small;
                public String large;
                public String medium;
            }
        }

        public static class DirectorsBean {
            /**
             * alt : https://movie.douban.com/celebrity/1047973/
             * avatars : {"small":"https://img3.doubanio.com/img/celebrity/small/230.jpg","large":"https://img3.doubanio.com/img/celebrity/large/230.jpg","medium":"https://img3.doubanio.com/img/celebrity/medium/230.jpg"}
             * name : 弗蘭克·德拉邦特
             * id : 1047973
             */

            public String alt;
            public AvatarsBeanX avatars;
            public String name;
            public String id;

            public static class AvatarsBeanX {
                /**
                 * small : https://img3.doubanio.com/img/celebrity/small/230.jpg
                 * large : https://img3.doubanio.com/img/celebrity/large/230.jpg
                 * medium : https://img3.doubanio.com/img/celebrity/medium/230.jpg
                 */

                public String small;
                public String large;
                public String medium;
            }
        }
    }
}

點擊請求數(shù)據(jù)按鈕律罢。獲取到返回的數(shù)據(jù)如下:

列表 ![Uploading 08_178546.png . . .]數(shù)據(jù)

當(dāng)然,TestPresenterImpl中的內(nèi)容是重點棍丐,其中g(shù)etMovieListData()方法里的內(nèi)容是retrofit和rxjava最基本的用法误辑!想必大家多少都見過。我們再來看下rxjava相關(guān)的代碼歌逢,其實它主要做了三個事情稀余。統(tǒng)一管理主線程、工作線程趋翻、請求返回后的回調(diào)處理睛琳!引入rxjava之前,三者都是自己管理踏烙。所以說师骗,它的引入極大的簡化了我們的工作。

08.png

下一篇將講述優(yōu)化封裝

相關(guān)鏈接

(四)安卓框架搭建之MVP+Retrofit+RxJava優(yōu)化

github源碼地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末讨惩,一起剝皮案震驚了整個濱河市辟癌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌荐捻,老刑警劉巖黍少,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異处面,居然都是意外死亡厂置,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門魂角,熙熙樓的掌柜王于貴愁眉苦臉地迎上來昵济,“玉大人,你說我怎么就攤上這事》梅蓿” “怎么了瞧栗?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長海铆。 經(jīng)常有香客問我迹恐,道長,這世上最難降的妖魔是什么卧斟? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任殴边,我火速辦了婚禮,結(jié)果婚禮上唆涝,老公的妹妹穿的比我還像新娘找都。我一直安慰自己,他們只是感情好廊酣,可當(dāng)我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布能耻。 她就那樣靜靜地躺著,像睡著了一般亡驰。 火紅的嫁衣襯著肌膚如雪晓猛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天凡辱,我揣著相機與錄音戒职,去河邊找鬼。 笑死透乾,一個胖子當(dāng)著我的面吹牛洪燥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播乳乌,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼捧韵,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了汉操?” 一聲冷哼從身側(cè)響起再来,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎磷瘤,沒想到半個月后芒篷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡采缚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年针炉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仰担。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡糊识,死狀恐怖绩社,靈堂內(nèi)的尸體忽然破棺而出摔蓝,到底是詐尸還是另有隱情赂苗,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布贮尉,位于F島的核電站拌滋,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏猜谚。R本人自食惡果不足惜败砂,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望魏铅。 院中可真熱鬧昌犹,春花似錦、人聲如沸览芳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽沧竟。三九已至铸敏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間悟泵,已是汗流浹背杈笔。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留糕非,地道東北人蒙具。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像朽肥,于是被迫代替她去往敵國和親禁筏。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,700評論 2 354

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