Android 优雅的让RxJava2.0+Retrofit2.0结合使用

前言

本文参考:

RxJava 与 Retrofit 结合的最佳实践http://gank.io/post/56e80c2c677659311bed9841

与上文不同的是:

  1. 本文采用最新的RxJava2.0与Retrifit2.0来实现,并针对于1.x不同的地方进行处理。
  2. 针对请求过程进行的封装,额外增加缓存策略和请求头部处理。
  3. RxJava2.0使用笔记:http://blog.csdn.net/demonliuhui/article/details/77848691
  4. Retrifit2.0使用笔记:http://blog.csdn.net/demonliuhui/article/details/77854530

使用配置

添加依赖
dependencies {
    ...
    compile 'io.reactivex.rxjava2:rxjava:2.1.3'
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
    compile 'com.squareup.okhttp3:okhttp:3.9.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.9.0'
    compile 'com.squareup.retrofit2:converter-scalars:2.3.0'
    ...
}

注意:

  1. 添加RxAndroid是为了解决线程调度问题。
  2. okhttp3:logging-interceptor是为了配置缓存策略,必须跟okhttp同一版本号,否则会报错:Failed resolution of: Lokhttp3/internal/Platform
  3. converter-scalars用于将请求结果转换为基本类型,一般为String
  4. converter-gson用于将请求结果转换为实体类型
添加权限
<uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
测试Api

豆瓣电影的Top250做测试连接,目标地址为:

https://api.douban.com/v2/movie/top250?start=0&count=10

返回的数据格式,大家自己访问下链接就看到了。

创建数据实体类

知道数据格式后我们创建对应数据实体类,方便处理获取后的数据。
这里只是简单获取几个数据,大家可以根据自己需求去编写自己想要的数据。

public class Movie {
    private String title;
    private List<Subjects> subjects;


    public String getTitle() {
        return title;
    }

    public List<Subjects> getSubjects() {
        return subjects;
    }
}

public class Subjects {
    private String title, year, id;

    public Subjects(String title, String year, String id) {
        this.title = title;
        this.year = year;
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public String getYear() {
        return year;
    }

    public String getId() {
        return id;
    }
}

最基本的RxJava+Retrofit

1.创建Service类

因为要结合使用RxJava,所以返回值就不在是一个Call了,而是一个Observable。

public interface ApiService {
    @GET("top250")
    Observable<Movie> getTopMovie(@Query("start") int start, @Query("count") int count);
}
2.创建Retrofit请求过程
  String baseUrl = "https://api.douban.com/v2/movie/";
 Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)               .addConverterFactory(ScalarsConverterFactory.create())//请求结果转换为基本类型
                .addConverterFactory(GsonConverterFactory.create())//请求的结果转为实体类
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())  //适配RxJava2.0, RxJava1.x则为RxJavaCallAdapterFactory.create()
                .build();
        apiService = retrofit.create(ApiService.class);
3.Activity发出请求(RxJava订阅)及处理数据

注意:RxJava2.0开始subscribe的对象不能是Subscriber,只能是Observer和Consumer,为了处理完整的过程我们这里选择Observer。 onSubscribe等同于onStart。

apiService.getTopMovie(0, 10)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Movie>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.d(TAG, "onSubscribe: ");
                    }

                    @Override
                    public void onNext(Movie movie) {
                        Log.d(TAG, "onNext: " + movie.getTitle());
                        List<Subjects> list = movie.getSubjects();
                        for (Subjects sub : list) {
                            Log.d(TAG, "onNext: " + sub.getId() + "," + sub.getYear() + "," + sub.getTitle());
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.e(TAG, "onError: " + e.getMessage());
                    }

                    @Override
                    public void onComplete() {
                        Log.d(TAG, "onComplete: Over!");
                    }
                });
4.运行结果
09-06 14:25:09.151 30008-30008/eee.rxjavaretrofit D/MainActivity: onSubscribe: 
09-06 14:25:11.308 30008-30008/eee.rxjavaretrofit D/MainActivity: onNext: 豆瓣电影Top250
09-06 14:25:11.308 30008-30008/eee.rxjavaretrofit D/MainActivity: onNext: 1292052,1994,肖申克的救赎
09-06 14:25:11.308 30008-30008/eee.rxjavaretrofit D/MainActivity: onNext: 1291546,1993,霸王别姬
09-06 14:25:11.308 30008-30008/eee.rxjavaretrofit D/MainActivity: onNext: 1295644,1994,这个杀手不太冷
09-06 14:25:11.309 30008-30008/eee.rxjavaretrofit D/MainActivity: onNext: 1292720,1994,阿甘正传
09-06 14:25:11.309 30008-30008/eee.rxjavaretrofit D/MainActivity: onNext: 1292063,1997,美丽人生
09-06 14:25:11.309 30008-30008/eee.rxjavaretrofit D/MainActivity: onNext: 1291561,2001,千与千寻
09-06 14:25:11.309 30008-30008/eee.rxjavaretrofit D/MainActivity: onNext: 1295124,1993,辛德勒的名单
09-06 14:25:11.309 30008-30008/eee.rxjavaretrofit D/MainActivity: onNext: 1292722,1997,泰坦尼克号
09-06 14:25:11.309 30008-30008/eee.rxjavaretrofit D/MainActivity: onNext: 3541415,2010,盗梦空间
09-06 14:25:11.309 30008-30008/eee.rxjavaretrofit D/MainActivity: onNext: 2131459,2008,机器人总动员
09-06 14:25:11.311 30008-30008/eee.rxjavaretrofit D/MainActivity: onComplete: Over!

这样就完成了最基本的RxJava+Retrofit,结果也与预期一致。
但是这样显然不能让我们去优雅的使用。毕竟优雅的复用已写过的代码才是我们的追求。
因此我们需要进一步对刚才的代码进行封装。

基本的封装RxJava+Retrofit

1.封装Retrofit请求过程

在之前的代码的基础上,创建Api.java用于封装Retrofit,代码如下:

public class Api {

    public static String baseUrl = "https://api.douban.com/v2/movie/";

    public static ApiService apiService;
    //单例
    public static ApiService getApiService() {
        if (apiService == null) {
            synchronized (Api.class) {
                if (apiService == null) {
                    new Api();
                }
            }
        }
        return apiService;
    }

    private Api() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())//请求的结果转为实体类
                //适配RxJava2.0,RxJava1.x则为RxJavaCallAdapterFactory.create()
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        apiService = retrofit.create(ApiService.class);
    }

}


2.封装线程管理和订阅

在使用RxJava的过程中,每次都重复写线程管理和订阅代码也是一件繁琐的事情。
创建ApiMethods用于封装线程管理和订阅的过程及调用请求。如下:

public class ApiMethods {

    /**
     * 封装线程管理和订阅的过程
     */
    public static void ApiSubscribe(Observable observable, Observer observer) {
        observable.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }

    /**
     * 用于获取豆瓣电影Top250的数据
     *
     * @param observer 由调用者传过来的观察者对象
     * @param start    起始位置
     * @param count    获取长度
     */
    public static void getTopMovie(Observer<Movie> observer, int start, int count) {
        ApiSubscribe(Api.getApiService().getTopMovie(start, count), observer);
    }
}
3.Activity中调用及处理数据
 Observer<Movie> observer = new Observer<Movie>() {
            @Override
            public void onSubscribe(Disposable d) {
                  Log.d(TAG, "onSubscribe: ");
            }

            @Override
            public void onNext(Movie movie) {
                Log.d(TAG, "onNext: " + movie.getTitle());
                List<Subjects> list = movie.getSubjects();
                for (Subjects sub : list) {
                    Log.d(TAG, "onNext: " + sub.getId() + "," + sub.getYear() + "," + sub.getTitle());
                }
            }

            @Override
            public void onError(Throwable e) {
                Log.e(TAG, "onError: " + e.getMessage());
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "onComplete: Over!");
            }
        };
        ApiMethods.getTopMovie(observer, 0, 10);
4.测试结果
09-06 15:14:01.413 16819-16819/eee.rxjavaretrofit D/MainActivity: onSubscribe: 
09-06 15:14:02.465 16819-16819/eee.rxjavaretrofit D/MainActivity: onNext: 豆瓣电影Top250
09-06 15:14:02.465 16819-16819/eee.rxjavaretrofit D/MainActivity: onNext: 1292052,1994,肖申克的救赎
09-06 15:14:02.465 16819-16819/eee.rxjavaretrofit D/MainActivity: onNext: 1291546,1993,霸王别姬
09-06 15:14:02.465 16819-16819/eee.rxjavaretrofit D/MainActivity: onNext: 1295644,1994,这个杀手不太冷
09-06 15:14:02.465 16819-16819/eee.rxjavaretrofit D/MainActivity: onNext: 1292720,1994,阿甘正传
09-06 15:14:02.465 16819-16819/eee.rxjavaretrofit D/MainActivity: onNext: 1292063,1997,美丽人生
09-06 15:14:02.465 16819-16819/eee.rxjavaretrofit D/MainActivity: onNext: 1291561,2001,千与千寻
09-06 15:14:02.465 16819-16819/eee.rxjavaretrofit D/MainActivity: onNext: 1295124,1993,辛德勒的名单
09-06 15:14:02.465 16819-16819/eee.rxjavaretrofit D/MainActivity: onNext: 1292722,1997,泰坦尼克号
09-06 15:14:02.465 16819-16819/eee.rxjavaretrofit D/MainActivity: onNext: 3541415,2010,盗梦空间
09-06 15:14:02.465 16819-16819/eee.rxjavaretrofit D/MainActivity: onNext: 2131459,2008,机器人总动员
09-06 15:14:02.465 16819-16819/eee.rxjavaretrofit D/MainActivity: onComplete: Over!

经过两次封装,如果有新的Api接口我们只需要在ApiService类中增加对应的接口方法,然后在ApiMethods类中写对应的请求方法即可。与基本的RxJava+Retrofit相比,在额外代码量和易用性上都明显占优。

进一步封装RxJava+Retrofit

看完上一步,你还是肯定还是会觉得,在Activity每次处理订阅返回的数据的时候都要实例化一个Observer对象,然后重写onSubscribe,onNext,onError,onComplete四个方法。虽然Android Studio一键就能补全代码,我们只用简单处理一下就ok了。但是那么多代码堆在那里还是让人不爽的。
因此我们进一步针对Observer进行封装。
针对重写方法的封装最好的方法就是使用接口+implements/继承的方式实现。
仔细分析会发现,其实除了onNext涉及数据处理,其余三个方法都可以进行模板化处理,比如显示一个Toast,输出错误信息等;当然如果你的业务需要,也可以按照onNext特别处理。
在之前代码的基础上。

1.新建监听接口

使用通配泛型,适用于所有类型的数据。

public interface ObserverOnNextListener<T> {
    void onNext(T t);
}
2.重写Observer
public class MyObserver<T> implements Observer<T> {
    private static final String TAG = "MyObserver";
    private ObserverOnNextListener listener;
    private Context context;

    public MyObserver(Context context, ObserverOnNextListener listener) {
        this.listener = listener;
        this.context = context;
    }

    @Override
    public void onSubscribe(Disposable d) {
        Log.d(TAG, "onSubscribe: ");
        //添加业务处理
    }

    @Override
    public void onNext(T t) {
        listener.onNext(t);
    }

    @Override
    public void onError(Throwable e) {
        Log.e(TAG, "onError: ", e);
        //添加业务处理
    }

    @Override
    public void onComplete() {
        Log.d(TAG, "onComplete: ");
        //添加业务处理
    }
}
3.Activity中使用
 ObserverOnNextListener<Movie> listener = new ObserverOnNextListener<Movie>() {
            @Override
            public void onNext(Movie movie) {
                Log.d(TAG, "onNext: " + movie.getTitle());
                List<Subjects> list = movie.getSubjects();
                for (Subjects sub : list) {
                    Log.d(TAG, "onNext: " + sub.getId() + "," + sub.getYear() + "," + sub.getTitle());
                }
            }
        };
        ApiMethods.getTopMovie(new MyObserver<Movie>(this, listener), 0, 10);
4.测试结果
09-06 16:01:59.918 3487-3487/eee.rxjavaretrofit D/MyObserver: onSubscribe: 
09-06 16:02:00.717 3487-3487/eee.rxjavaretrofit D/MainActivity: onNext: 豆瓣电影Top250
09-06 16:02:00.717 3487-3487/eee.rxjavaretrofit D/MainActivity: onNext: 1292052,1994,肖申克的救赎
09-06 16:02:00.717 3487-3487/eee.rxjavaretrofit D/MainActivity: onNext: 1291546,1993,霸王别姬
09-06 16:02:00.717 3487-3487/eee.rxjavaretrofit D/MainActivity: onNext: 1295644,1994,这个杀手不太冷
09-06 16:02:00.717 3487-3487/eee.rxjavaretrofit D/MainActivity: onNext: 1292720,1994,阿甘正传
09-06 16:02:00.717 3487-3487/eee.rxjavaretrofit D/MainActivity: onNext: 1292063,1997,美丽人生
09-06 16:02:00.717 3487-3487/eee.rxjavaretrofit D/MainActivity: onNext: 1291561,2001,千与千寻
09-06 16:02:00.717 3487-3487/eee.rxjavaretrofit D/MainActivity: onNext: 1295124,1993,辛德勒的名单
09-06 16:02:00.717 3487-3487/eee.rxjavaretrofit D/MainActivity: onNext: 1292722,1997,泰坦尼克号
09-06 16:02:00.717 3487-3487/eee.rxjavaretrofit D/MainActivity: onNext: 3541415,2010,盗梦空间
09-06 16:02:00.717 3487-3487/eee.rxjavaretrofit D/MainActivity: onNext: 2131459,2008,机器人总动员
09-06 16:02:00.718 3487-3487/eee.rxjavaretrofit D/MyObserver: onComplete: 

优雅的封装RxJava+Retrofit

上面的代码可谓是封装的彻底了,但是还不够优雅。
如何优雅?
网络请求一般都是耗时的,我们需要在进行网络请求的时候有一个进度框,增加用户体验。
根据上一步,我们只需要将进度框show在onSubscribe中,然后在onError/onComplete里cancel掉就行了。如果用户取消关闭了进度框,那么也随之取消了当前的Http请求。

1.编写ProgressDialog类代码

Handler接收两个消息来控制显示Dialog还是关闭Dialog。

public class ProgressDialogHandler extends Handler {
    public static final int SHOW_PROGRESS_DIALOG = 1;
    public static final int DISMISS_PROGRESS_DIALOG = 2;

    private ProgressDialog pd;

    private Context context;
    private boolean cancelable;
    private ProgressCancelListener mProgressCancelListener;

    public ProgressDialogHandler(Context context, ProgressCancelListener
            mProgressCancelListener, boolean cancelable) {
        super();
        this.context = context;
        this.mProgressCancelListener = mProgressCancelListener;
        this.cancelable = cancelable;
    }

    private void initProgressDialog() {
        if (pd == null) {
            pd = new ProgressDialog(context);

            pd.setCancelable(cancelable);

            if (cancelable) {
                pd.setOnCancelListener(new DialogInterface.OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialogInterface) {
                        mProgressCancelListener.onCancelProgress();
                    }
                });
            }

            if (!pd.isShowing()) {
                pd.show();
            }
        }
    }

    private void dismissProgressDialog() {
        if (pd != null) {
            pd.dismiss();
            pd = null;
        }
    }

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case SHOW_PROGRESS_DIALOG:
                initProgressDialog();
                break;
            case DISMISS_PROGRESS_DIALOG:
                dismissProgressDialog();
                break;
        }
    }
}

此处安全按照参考文章来写的,当然你也可以直接ProgressDialog dialog = new ProgressDialog(context);

2.编写监听取消的接口类
public interface ProgressCancelListener {
    void onCancelProgress();
}

3.在MyObserver中添加ProgressDialog

将上面ProgressDialog在Observer中初始化,并在相应的位置进行显示和隐藏。

public class ProgressObserver<T> implements Observer<T>, ProgressCancelListener {
    private static final String TAG = "ProgressObserver";
    private ObserverOnNextListener listener;
    private ProgressDialogHandler mProgressDialogHandler;
    private Context context;
    private Disposable d;

   public ProgressObserver(Context context, ObserverOnNextListener listener) {
        this.listener = listener;
        this.context = context;
        mProgressDialogHandler = new ProgressDialogHandler(context, this, true);
    }


    private void showProgressDialog() {
        if (mProgressDialogHandler != null) {
            mProgressDialogHandler.obtainMessage(ProgressDialogHandler.SHOW_PROGRESS_DIALOG).sendToTarget();
        }
    }

    private void dismissProgressDialog() {
        if (mProgressDialogHandler != null) {
            mProgressDialogHandler.obtainMessage(ProgressDialogHandler.DISMISS_PROGRESS_DIALOG)
                    .sendToTarget();
            mProgressDialogHandler = null;
        }
    }

    @Override
    public void onSubscribe(Disposable d) {
        this.d = d;
        showProgressDialog();
    }

    @Override
    public void onNext(T t) {
        listener.onNext(t);
    }

    @Override
    public void onError(Throwable e) {
        dismissProgressDialog();
        Log.e(TAG, "onError: ", e);
    }

    @Override
    public void onComplete() {
        dismissProgressDialog();
        Log.d(TAG, "onComplete: ");
    }

    @Override
    public void onCancelProgress() {
    	 //如果处于订阅状态,则取消订阅
        if (!d.isDisposed()) {
            d.dispose();
        }
    }
}
5.Activity中使用
 ObserverOnNextListener<Movie> listener = new ObserverOnNextListener<Movie>() {
            @Override
            public void onNext(Movie movie) {
                Log.d(TAG, "onNext: " + movie.getTitle());
                List<Subjects> list = movie.getSubjects();
                for (Subjects sub : list) {
                    Log.d(TAG, "onNext: " + sub.getId() + "," + sub.getYear() + "," + sub.getTitle());
                }
            }
        };
       ApiMethods.getTopMovie(new ProgressObserver<Movie>(this, listener), 0, 10);
6.测试结果
09-06 16:32:05.135 6823-6823/eee.rxjavaretrofit D/ProgressObserver: onSubscribe: 
09-06 16:32:05.990 6823-6823/eee.rxjavaretrofit D/MainActivity: onNext: 豆瓣电影Top250
09-06 16:32:05.990 6823-6823/eee.rxjavaretrofit D/MainActivity: onNext: 1292052,1994,肖申克的救赎
09-06 16:32:05.990 6823-6823/eee.rxjavaretrofit D/MainActivity: onNext: 1291546,1993,霸王别姬
09-06 16:32:05.990 6823-6823/eee.rxjavaretrofit D/MainActivity: onNext: 1295644,1994,这个杀手不太冷
09-06 16:32:05.990 6823-6823/eee.rxjavaretrofit D/MainActivity: onNext: 1292720,1994,阿甘正传
09-06 16:32:05.990 6823-6823/eee.rxjavaretrofit D/MainActivity: onNext: 1292063,1997,美丽人生
09-06 16:32:05.990 6823-6823/eee.rxjavaretrofit D/MainActivity: onNext: 1291561,2001,千与千寻
09-06 16:32:05.990 6823-6823/eee.rxjavaretrofit D/MainActivity: onNext: 1295124,1993,辛德勒的名单
09-06 16:32:05.990 6823-6823/eee.rxjavaretrofit D/MainActivity: onNext: 1292722,1997,泰坦尼克号
09-06 16:32:05.990 6823-6823/eee.rxjavaretrofit D/MainActivity: onNext: 3541415,2010,盗梦空间
09-06 16:32:05.990 6823-6823/eee.rxjavaretrofit D/MainActivity: onNext: 2131459,2008,机器人总动员
09-06 16:32:05.992 6823-6823/eee.rxjavaretrofit D/ProgressObserver: onComplete: 

优化Retrofit,设置缓存,超时策略

使用OkHttpClient对Retrofit设置设置缓存,超时策略。

public class ApiStrategy {

    public static String baseUrl = "https://api.douban.com/v2/movie/";
    //读超时长,单位:毫秒
    public static final int READ_TIME_OUT = 7676;
    //连接时长,单位:毫秒
    public static final int CONNECT_TIME_OUT = 7676;


    public static ApiService apiService;
    public static ApiService getApiService() {
        if (apiService == null) {
            synchronized (Api.class) {
                if (apiService == null) {
                    new ApiStrategy();
                }
            }
        }
        return apiService;
    }

    private ApiStrategy() {
        HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor();
        logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        //缓存
        File cacheFile = new File(MyApplication.getContext().getCacheDir(), "cache");
        Cache cache = new Cache(cacheFile, 1024 * 1024 * 100); //100Mb
        //增加头部信息
        Interceptor headerInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request build = chain.request().newBuilder()
                        //.addHeader("Content-Type", "application/json")//设置允许请求json数据
                        .build();
                return chain.proceed(build);
            }
        };

        //创建一个OkHttpClient并设置超时时间
        OkHttpClient client = new OkHttpClient.Builder()
                .readTimeout(READ_TIME_OUT, TimeUnit.MILLISECONDS)
                .connectTimeout(CONNECT_TIME_OUT, TimeUnit.MILLISECONDS)
                .addInterceptor(mRewriteCacheControlInterceptor)
                .addNetworkInterceptor(mRewriteCacheControlInterceptor)
                .addInterceptor(headerInterceptor)
                .addInterceptor(logInterceptor)
                .cache(cache)
                .build();

        Retrofit retrofit = new Retrofit.Builder()
                .client(client)
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())//请求的结果转为实体类
                //适配RxJava2.0,RxJava1.x则为RxJavaCallAdapterFactory.create()
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        apiService = retrofit.create(ApiService.class);
    }


    /**
     * 设缓存有效期为两天
     */
    private static final long CACHE_STALE_SEC = 60 * 60 * 24 * 2;

    /**
     * 云端响应头拦截器,用来配置缓存策略
     * Dangerous interceptor that rewrites the server's cache-control header.
     */
    private final Interceptor mRewriteCacheControlInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            String cacheControl = request.cacheControl().toString();
            if (!NetWorkUtils.isNetConnected(MyApplication.getContext())) {
                request = request.newBuilder()
                        .cacheControl(TextUtils.isEmpty(cacheControl) ? CacheControl
                                .FORCE_NETWORK : CacheControl.FORCE_CACHE)
                        .build();
            }
            Response originalResponse = chain.proceed(request);
            if (NetWorkUtils.isNetConnected(MyApplication.getContext())) {
                return originalResponse.newBuilder()
                        .header("Cache-Control", cacheControl)
                        .removeHeader("Pragma")
                        .build();
            } else {
                return originalResponse.newBuilder()
                        .header("Cache-Control", "public, only-if-cached, max-stale=" +
                                CACHE_STALE_SEC)
                        .removeHeader("Pragma")
                        .build();
            }
        }
    };
}

总结

目前为止,就封装完毕了。
现在我们再写一个新的网络请求,步骤是这样的:

  1. 在Service中定义一个新的方法。
  2. 在ApiMethods封装对应的请求(代码基本可以copy)
  3. 创建一个ObserverOnNextListener处理请求数据。
  4. 在onNext处理业务逻辑。

代码下载

CSDN代码下载,是Module不是project:http://download.csdn.net/download/demonliuhui/9966975
PS:因为是Module的代码,所以请谨慎导入。

GitHub:https://github.com/MyAndroidDemo/RxJavaRetrofitDemo

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值