主页 > 开发文档 > Android开发 网络框架之Retrofit + RxJava + OkHttp

Android开发 网络框架之Retrofit + RxJava + OkHttp

现在android网络请求大部分已经换成了Retrofit2.0 +RxJava + OkHttp3.0,Retrofit 使用接口的方式,负责请求的数据和请求的结果,OkHttp 负责请求的过程,RxJava 负责异步,各种线程之间的切换。毫无疑问这三剑客 已成为当前Android 网络请求最流行的方式。

简介

Retrofit: Retrofit是Square 公司开发的一款基于restful风格接口的Android 网络请求的框架,对Okhttp做了一层封装。网络请求还是基于Okhttp,我们只需要通过简单的配置就能使用Retrofit来进行网络请求。

RxJava:RxJava 在 GitHub 主页上介绍 "a library for composing asynchronous and event-based programs using observable sequences for the Java VM"(一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库)。总之,rxjava让异步操作变得非常简单。

OkHttp: Square 公司开源的网络请求库

基本使用

HTTP协议中共定义了八种方法或者叫“动作”来表明对Request-URI指定的资源的不同操作方式,分别是OPTIONS、HEAD、GET、POST、PUT、DELETE、TRACE、CONNECT,介绍就省略了。

虽然有这么多种请求方式,但App的接口请求无非就是数据的增删改查,增删改查对应到Restful风格接口上也就是post,delete,put,get四种请求。在Retrofit框架提供的注解中,其中HTTP注解有五个,用来修饰请求方法,除了post,delete,put,get还有一个head。除了这五种网络请求方式外,App无非还会用到retrofit的单文件或者多文件的上传下载,同步请求或者异步请求的处理,还有okhttp数据缓存的问题。

注解 请求方式 用途
@Path GET 用于替换Url路径中的变量字符
@Query GET 用于拼接在Url路径后的查询参数,但相对于直接在Url后拼接,@Query则是添加一个变量
@QueryMap GET 效果等同于多个@Query 参数为Map类型
@FormUrlEncoded/@Field POST @FormUrlEncoded修饰表单域,每个表单域子件key-value采用@Field修饰
@Body POST 可以指定一个对象作为HTTP请求体@Body
@FormUrlEncoded/@Field PUT @FormUrlEncoded修饰表单域,每个表单域子件key-value采用@Field修饰
@HTTP/@Body DELETE @HTTP修饰表单域,以指定一个对象作为HTTP请求体@Body,此时表单域一定要写上hasBody = true
@Multipart/@Part或者@PartMap POST 文件上传使用,@Multipart修饰表单域,参数@Part修饰或者参数使用@PartMap

举例说明

引入依赖

  1. compile 'com.squareup.retrofit2:retrofit:2.2.0'

  2. compile 'com.squareup.retrofit2:adapter-rxjava:2.2.0'

  3. compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta3'

  4. compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'

  5. compile 'com.squareup.okhttp3:okhttp:3.4.1'

  6. compile 'io.reactivex:rxjava:1.1.9'

  7. compile 'io.reactivex:rxandroid:1.2.1'

创建Retrofit对象

  1. public class RetrofitManager {

  2. private static RetrofitManager mRetrofitManager;

  3. private Retrofit mRetrofit;

  4.  

  5. private RetrofitManager(){

  6.    initRetrofit();

  7. }

  8.  

  9. public static synchronized RetrofitManager getInstance(){

  10.  

  11.    if (mRetrofitManager == null){

  12.        mRetrofitManager = new RetrofitManager();

  13.    }

  14.    return mRetrofitManager;

  15. }

  16.  

  17. private void initRetrofit() {

  18.    HttpLoggingInterceptor LoginInterceptor = new HttpLoggingInterceptor();

  19.    LoginInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

  20.  

  21.    OkHttpClient.Builder builder = new OkHttpClient.Builder();

  22.    builder.addInterceptor(new RspCheckInterceptor());

  23.  

  24.    if (AppConfig.DEBUG){

  25.        builder.addInterceptor(LoginInterceptor);

  26.    }

  27.  

  28.    builder.connectTimeout(15, TimeUnit.SECONDS);

  29.    builder.readTimeout(20, TimeUnit.SECONDS);

  30.    builder.writeTimeout(20, TimeUnit.SECONDS);

  31.    builder.retryOnConnectionFailure(true);

  32.    OkHttpClient client = builder.build();

  33.  

  34.    Gson gson = new GsonBuilder()

  35.            .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")

  36.            .setExclusionStrategies(new ExclusionStrategy() {

  37.                                        @Override

  38.                                        public boolean shouldSkipField(FieldAttributes f) {

  39.                                            return false;

  40.                                        }

  41.  

  42.                                        @Override

  43.                                        public boolean shouldSkipClass(Class<?> clazz) {

  44.                                            return false;

  45.                                        }

  46.                                    })

  47.            .create();

  48.  

  49.    mRetrofit = new Retrofit.Builder()

  50.            .baseUrl(AppConfig.BASE_URL)

  51.            .addConverterFactory(GsonConverterFactory.create(gson))

  52.            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())

  53.            .client(client)

  54.            .build();

  55. }

  56.  

  57. public <T> T createReq(Class<T> reqServer){

  58.    return mRetrofit.create(reqServer);

  59. }

  60. }

创建访问API的请求

  1. /**

  2. * 添加标签

  3. *

  4. * @param supplier_id

  5. * @param staff_id

  6. * @param name

  7. * @param type

  8. * @return

  9. */

  10. @FormUrlEncoded

  11. @POST("memberservice/addMemberTag/suppliers/{supplier_id}/operator/{staff_id}")

  12. Observable<BaseResponse> addMemberTag(@Path("supplier_id") String supplier_id,

  13.                                      @Path("staff_id") String staff_id,

  14.                                      @Field("name") String name, @Field("type") String type, @Field("timestamp") String timestamp);

  15.  

  16. /**

  17. * 删除标签(注意一定要写hasBody = true,否则delete不能使用body参数请求)

  18. *

  19. * @param supplier_id

  20. * @param operator_id

  21. * @return

  22. */

  23. @HTTP(method = "DELETE", path = "memberservice/delMemberTag/suppliers/{supplier_id}/operator/{operator_id}", hasBody = true)

  24. Observable<BaseResponse> deletMemberTag(@Path("supplier_id") String supplier_id,

  25.                                        @Path("operator_id") String operator_id,

  26.                                        @Body RequestBody content);

  27.  

  28.  

  29. /**

  30. * 修改标签

  31. *

  32. * @param supplier_id

  33. * @param operator_id

  34. * @param map

  35. * @return

  36. */

  37. @FormUrlEncoded

  38. @PUT("memberservice/updateMemberTag/suppliers/{supplier_id}/operator/{operator_id}")

  39. Observable<BaseResponse> updateMemberTag(@Path("supplier_id") String supplier_id,

  40.                                         @Path("operator_id") String operator_id,

  41.                                         @FieldMap Map<String, String> map);

  42.  

  43.  

  44. /**

  45. * 查询标签

  46. *

  47. * @param supplier_id

  48. * @param staff_id

  49. * @return

  50. */

  51. @GET("memberservice/queryStaffTag/suppliers/{supplier_id}/operator/{staff_id}")

  52. Observable<BaseResponse<TagsBean>> queryMemberTag(@Path("supplier_id") String supplier_id,

  53.                                                  @Path("staff_id") String staff_id,

  54.                                                  @Query("timestamp") String timestamp);

  55. }

发送请求以及处理结果

  1.  RetrofitManager.getInstance().createReq(Api.class).addMemberTag(supply_id, staff_id, data, "2", getTime()).subscribeOn(Schedulers.io())

  2.                            .observeOn(AndroidSchedulers.mainThread())

  3.                            .subscribeOn(Schedulers.io())

  4.                            .subscribe(new Subscriber<BaseResponse>() {

  5.                                @Override

  6.                                public void onCompleted() {

  7.  

  8.                                }

  9.  

  10.                                @Override

  11.                                public void onError(Throwable e) {

  12.  

  13.                                      //处理请求失败的操作

  14.                                }

  15.  

  16.                                @Override

  17.                                public void onNext(BaseResponse baseResponse) {

  18.  

  19.                                    //处理成功后的结果

  20.                                }

  21.  

  22.                            });

多图以及单图上传
方法一:

  1. @Multipart

  2. @POST("suppliers/{supplier_id}/staff/{staff_id}/meeting/{meeting_id}/upload")

  3. Observable<BaseResponse> uploadePics(

  4.        @Path("supplier_id")String supplier_id,@Path("staff_id")String staff_id,

  5.        @Path("meeting_id")String meeting_id,@Part List<MultipartBody.Part> partList);

  6.  

  7.  

  8.     MultipartBody.Builder builder = new MultipartBody.Builder()

  9.                                .setType(MultipartBody.FORM)//表单类型

  10.                                .addFormDataPart("summary_position", formatted_address); //地理位置

  11.  

  12.                        //单张或者多张

  13.                        for (int i = 0; i < listString.size(); i++) {

  14.                            File file = new File(listString.get(i));

  15.                            RequestBody imageBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);

  16.                            builder.addFormDataPart("summary_pics[]", file.getName(), imageBody);

  17.                        }

  18.  

  19.                        List<MultipartBody.Part> parts = builder.build().parts();

  20.  

  21.                     RetrofitManager2.getInstance().createReq(PhpApi.class).uploadePics(

  22.                                supplier_id,staff_id,meeting_id,parts)

  23.                                .observeOn(AndroidSchedulers.mainThread())

  24.                                .subscribeOn(Schedulers.io())

  25.                                .subscribe(new Subscriber<BaseResponse>() {

  26.                                    @Override

  27.                                    public void onCompleted() {

  28.  

  29.                                    }

  30.  

  31.                                    @Override

  32.                                    public void onError(Throwable e) {

  33.  

  34.                                    }

  35.  

  36.                                    @Override

  37.                                    public void onNext(BaseResponse baseResponse) {

  38.  

  39.                                    }

  40.                                });

方法二:

  1. Observable<BaseResponse> uploadePics2(

  2.        @Path("supplier_id")String supplier_id,@Path("staff_id")String staff_id,

  3.        @Path("meeting_id")String meeting_id,

  4.        @PartMap Map<String, RequestBody> params);

  5.  

  6.                        //单张或多张图片

  7.                        List<File>files = new ArrayList<File>();

  8.                        for (int i = 0; i < listString.size(); i++) {

  9.                            File file = new File(listString.get(i));

  10.                            files.add(file);

  11.                        }

  12.  

  13.                        //组装partMap对象

  14.                        Map<String, RequestBody> partMap = new HashMap<>();

  15.                        for(File file : files ){

  16.                            RequestBody fileBody = RequestBody.create(MediaType.parse("image/*"), file);

  17.                            partMap.put("summary_pics[]\"; filename=\""+file.getName()+"\"", fileBody);

  18.                        }

  19.                        RequestBody formatted_addressString = RequestBody.create(MediaType.parse("text/plain"), formatted_address);

  20.                        partMap.put("summary_position" , formatted_addressString);

  21.  

  22.  

  23.                        RetrofitManager2.getInstance().createReq(PhpApi.class).uploadePics2(

  24.                                supplier_id,staff_id,meeting_id,partMap)

  25.                                .observeOn(AndroidSchedulers.mainThread())

  26.                                .subscribeOn(Schedulers.io())

  27.                                .subscribe(new Subscriber<BaseResponse>() {

  28.                                    @Override

  29.                                    public void onCompleted() {

  30.  

  31.                                    }

  32.  

  33.                                    @Override

  34.                                    public void onError(Throwable e) {

  35.  

  36.                                    }

  37.  

  38.                                    @Override

  39.                                    public void onNext(BaseResponse baseResponse) {

  40.  

  41.                                    }

  42.                                });