RxJava网络请求书写

背景

项目中使用 Rxjava 进行网络请求,请求的方式有 get 请求和 post 请求,而请求中 有时候 需要 请求头 head,有时候需要 请求 json 串,琳琳种种,梳理下思路:

1. get 请求

无参数-get

@GET("login/sys")
ObservablegetTKUrl();

有参数-get ,用 Query 查询字段

@GET("customer/login")
Observable<PolicRecordBean> getPolicyRecord(
          @Query("id") String id,
          @Query("token") String token   );

多个参数请求

@GET("News")
Call<NewsBean> getItem(
            @Query("newsId") String newsId,
            @QueryMap Map<String, String> map);

请求示例:https://way.jd.com/jisuapi/get?channel=头条&num=10

QueryMap:mapkeychannelvalue存“头条”,keynumvalue10

2. post请求 – 大部分为有参,增加安全性

2.1 post 简单请求

@POST("preservation/login")
Observable<HeadBanner> getHeadBanner(
            @Query("token") String token
    );

2.2 post 普通请求 Field 与 FormUrlEncoded 联用

@FormUrlEncoded
@POST("preservation/login")
Observable<Loan> loan(
        @Field("param") String param,
        @Field("sign") String sign,
        @Query("token") String token
    );

FormUrlEncoded: form表单;

Multipart:form表单,适合大文件;

2.3 多参数-post

 @FormUrlEncoded
 @POST("cos/getPubSignParams")
 Observable<TencentCloudParams> getTencentCloudParams(
          @FieldMap Map<String, String> params,
          @Query("token") String token
    );

2.4 补全url

@FormUrlEncoded
@POST("Comments/{newsId}")
Call<Comment> reportComment(
        @Path("newsId") String commentId,
        @Query("access_token") String access_token,
        @Field("reason") String reason);

2.5 body 相当于多个@Field,以对象的形式提交

    @POST("cos/getSignParamsNew")
    Observable<TencentCloudKeyParamsBean> getTencentCloudParamsSet(
            @Body RequestBody body,
            @Query("token") String token
    );

常见的写法
      2.5.1 自定义 bean
       DBean request=new DBean ();
       request.setAA(aa);
        Gson gson = new Gson();
        String param = gson.toJson(request);
        RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),param);
        HttpUtil.init(HttpUtil.sspHttpUtils().getCustomDetailsList(body, App.TOKEN), new Subscriber<GetCustomBean>() {
    
    
            @Override
            public void onCompleted() {
    
      }
            @Override
            public void onError(Throwable e) {
    
     }
            @Override
            public void onNext(GetCustomBean getCustomBean) {
    
    2.5.2 使用jsonobject

         JSONObject jsonObject = new JSONObject();
            try {
    
    
            jsonObject.put("AA", aa);
        } catch (JSONException e) {
    
    
            e.printStackTrace();
        }
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), jsonObject.toString());
        HttpUtil.init(HttpUtil.sspHttpUtils().login(requestBody), new Subscriber<DBean>() {
    
    
            @Override
            public void onCompleted() {
    
      }
            @Override
            public void onError(Throwable e) {
    
                }
            @Override
            public void onNext(DBean bean) {
    
    }

  2.5.3 使用map
         Map map=new HashMap();
         map.put("AA",aa);
         RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), new Gson().toJson(map));
         HttpUtil.init(HttpUtil.sspHttpUtils().login(requestBody), new Subscriber<DBean>() {
    
    
            @Override
            public void onCompleted() {
    
      }
            @Override
            public void onError(Throwable e) {
    
                }
            @Override
            public void onNext(DBean bean) {
    
    }

2.6 加请求头 Headers

@Headers 用于添加固定请求头,可以同时添加多个。通过该注解添加的请求头不会相互覆盖,而是共同存在
@Header 作为方法的参数传入,用于添加不固定值的Header,该注解会更新已有的请求头

    @Headers("secret:AA")
    @POST("customer/login")
    Observable<DBean> getDB(
            @Body RequestBody body,
            @Query("token") String token,
            @Query("sign") String sign
    );

   @Headers("Cache-Control: max-age=120")
   @GET("请求地址")
   Observable<HttpResult> getInfo();
或者
   @GET("请求地址")
   Observable<HttpResult> getInfo(@Header("token") String token);

2.7 part 上传文本+文件

使用Retrofit+RxJava实现网络请求 https://www.jianshu.com/p/092452f287db

1)上传单个文本和单个文件
@Multipart
@POST("请求地址")
Observable<HttpResult> upLoadTextAndFile(@Part("textKey") RequestBody textBody, 
                @Part("fileKey\"; filename=\"test.png") RequestBody fileBody);

第一个参数用于传文本,

> --- @Part("textKey")中的"textKey"为文本参数的参数名。

> --- RequestBody textBody为文本参数的参数值,生成方式如下:
> RequestBody textBody = RequestBody.create(MediaType.parse("text/plain"), text);

第二个参数用于传文件,

> --- @Part("fileKey"; filename="test.png")
> 其中的"fileKey"为文件参数的参数名(由服务器后台提供)
> 其中的"test.png"一般是指你希望保存在服务器的文件名字,传入File.getName()即可

> --- RequestBody fileBody为文件参数的参数值,生成方法如下:
> RequestBody fileBody = RequestBody.create(MediaType.parse("image/png"), file);
> 
> (这里文件类型以png图片为例,所以MediaType为"image/png"> 不同文件类型对应不同的type,具体请参考[http://tool.oschina.net/commons](http://tool.oschina.net/commons)

上传多个文本和多个文件(通过Map来传入)

@Multipart
@POST("")
Observable<HttpResult> upLoadTextAndFiles(@PartMap Map<String, RequestBody> textBodyMap, @PartMap Map<String, RequestBody> fileBodyMap);

第一个参数用于传文本,

Map的key为String,内容请参考上方“上传文本和单个文件”中@Part()里的值。
Map的value值为RequestBody,内容请参考上方“上传文本和单个文件”中RequestBody的生成。

第二个参数用于传文件,

Map的key为String,内容请参考上方“上传文本和单个文件”中@Part()里的值。
Map的value值为RequestBody,内容请参考上方“上传文本和单个文件”中RequestBody的生成。

另外补充多一种上传方式(2018/07/16),以上传多个文本和多个文件为例

@POST("")
Observable<HttpResult> upLoadTextAndFiles(@Body MultipartBody multipartBody);

MultipartBody 的生成方式如下:
MultipartBody.Builder builder = new MultipartBody.Builder();
//文本部分
builder.addFormDataPart("fromType", "1");
builder.addFormDataPart("content", "意见反馈内容");
builder.addFormDataPart("phone", "17700000066");

//文件部分
RequestBody requestBody = RequestBody.create(MediaType.parse("image/jpg"), file);
builder.addFormDataPart("image", file.getName(), requestBody); // “image”为文件参数的参数名(由服务器后台提供)

builder.setType(MultipartBody.FORM);
MultipartBody multipartBody = builder.build();


下载文件

//下载大文件时,请加上@Streaming,否则容易出现IO异常
@Streaming
@GET("请求地址")
Observable<ResponseBody> downloadFile();
//ResponseBody是Retrofit提供的返回实体,要下载的文件数据将包含在其中

part — eg:

  /**
     * 文本参数转换
     * @param value
     * @return
     */
    public static RequestBody toRequestBody(String value) {
    
    
        RequestBody body = RequestBody.create(MediaType.parse("multipart/form-data"), value);
        return body;
    }

    @Multipart
    @POST("/Card")
    Observable<SubmitEditVisitingCardInfoBean> submitEditVisitingCardInfo(@Part("staffNumber")   RequestBody staffNumber,
                                                                          @Part MultipartBody.Part headimg,
                                                                          @Part("workAge") RequestBody workAge,
                                                                          @Part("wxNum") RequestBody wxNum,
                                                                          @Part MultipartBody.Part wximg,
                                                                          @Part("tags") RequestBody tags,
                                                                          @Part("sex") RequestBody sex,
                                                                          @Part("proSeleIdList") RequestBody proSeleIdList);
    private MultipartBody.Part wxBodyP;
    private MultipartBody.Part headBodyP;
                    File head = new File(currentHeadImgUri.getPath());
                    RequestBody headBoyd = RequestBody.create(MediaType.parse("multipart/form-data"), head);
                    headBodyP = MultipartBody.Part.createFormData("headImgFile", "head.png", headBoyd);
  
                    File wx = new File(currentRqCodeUri.getPath());
                    RequestBody wxBody = RequestBody.create(MediaType.parse("multipart/form-data"), wx);
                    wxBodyP = MultipartBody.Part.createFormData("wx2DImgFile", "wxxx.png", wxBody);
             
               HttpUtil.init(HttpUtil.sspHttpUtils().submitCardInfo(
                        toRequestBody(staf),
                        headBodyP,
                        toRequestBody(getWorkAge()),
                        toRequestBody(getWxNum()),
                        wxBodyP,
                        toRequestBody(getTags()),
                        toRequestBody(getSex()),
                        toRequestBody(getSelectedRecommendId())
                ), new Subscriber<CardInfoBean>() {
    
    
                    @Override
                    public void onCompleted() {
    
     }
                    @Override
                    public void onError(Throwable e) {
    
       }
                    @Override
                    public void onNext(CardInfoBean card) {
    
    }

Retrofit注解详解

Retrofit 共22个注解,这节就专门介绍这22个注解,为帮助大家更好理解我将这22个注解分为三类,并用表格的形式展现出来,表格上说得并不完整,具体的见源码上的例子注释。

第一类:HTTP请求方法

分类 名称 备注
请求方法 GET 分别对应HTTP的请求方法,都接收一个字符串表示接口path与baseUrl组成完整的Url不过也可以不指定结合下面的@Url注解使用,url中也可以使用变量如{id}并使用@Path("id")注解为{id}提供值,如下面的例子
POST
PUT
DELETE
PATCH
HEAD
OPTIONS
HTTP 可用于替换以上7个,以及其他扩展方法
@GET("blog/{
    
    id}")
Call<ResponseBody> getBlog(@Path("id") int id);

以上表格中的除HTTP以外都对应了HTTP标准中的请求方法,而HTTP注解则可以代替以上方法中的任意一个注解,有3个属性:methodpath,hasBody,下面是用HTTP注解实现上面

  /**
     * method 表示请求的方法,区分大小写
     * path表示路径
     * hasBody表示是否有请求体
     */
    @HTTP(method = "GET", path = "blog/{id}", hasBody = false)
    Call<ResponseBody> getBlog(@Path("id") int id);

**注:**method 的值 retrofit 不会做处理,所以要自行保证其准确性,之前使用小写也可以是因为示例源码中的服务器不区分大小写,所以希望大家注意;

第二类:标记类

分类 名称 备注
表单请求 FormUrlEncoded 表示请求体是一个Form表单与@POST结合使用,Content-Type:application/x-www-form-urlencoded
Multipart 表示请求体是一个支持文件上传的Form表单,与@POST结合使用做文件的上传,你看到待文件上传的网页就是用的这种请求方式,Content-Type:multipart/form-data
标记 Streaming 表示响应体的数据用流的形式返回,主要做大文件下载,如果没有使用该注解,默认会把数据全部载入内存,之后你通过流获取数据也不过是读取内存中的数据,所以如你的返回的数据比较大,你需要使用这个注解

第三类:参数类

分类 名称 备注
作用于方法 Headers 用于添加请求头
作用于方法参数(这里指的是形参) Headers 用于添加不固定值的Header
Body 用于非表单请求(见下方)
Field 用于表单字段,Field和FieldMap与FormUrlEncoded注解配合,Part和PartMap与Multipart注解配合,适合有文件上传的情况,FieldMap的接收类型是Map

注1:{占位符}和**PATH尽量只用在URL的path部分,url中的参数使用QueryQueryMap 代替,保证接口定义的简洁
注2:QueryFieldPart这三者都支持
数组**和实现了Iterable接口的类型,如ListSet等,方便向后台传递数组。

Call<ResponseBody> foo(@Query("ids[]") List<Integer> ids);
//结果:ids[]=0&ids[]=1&ids[]=2

参考文档:

你真的会用Retrofit2吗?Retrofit2完全教程
Content-Type四种常见取值
Http请求中Content-Type
Retrofit进行post提交json数据

猜你喜欢

转载自blog.csdn.net/Grekit_Sun/article/details/113743867