Retrofit2.0实践记录

前言

Type-safe HTTP client for Android and Java by Square, Inc.

官网:http://square.github.io/retrofit/

API:http://square.github.io/retrofit/2.x/retrofit/

参考:http://gank.io/post/56e80c2c677659311bed9841

http://blog.csdn.net/lmj623565791/article/details/51304204


简介

主要记录一下GET,POST请求,以及Query,Path等注解的理解以及使用。主要有:

  • GET方式请求String
  • GET方式请求Json
  • GET方式访问自签名网站https
  • POST方式请求Json(需要header情况)

Converter(转化器)

Converter:用于对象转化的。默认情况下,Retrofit 请求结果为responsebody型

  Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();

    // Remove the body‘s source (the only stateful object) so we can pass the response along.
    rawResponse = rawResponse.newBuilder()
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();

    int code = rawResponse.code();
    if (code < 200 || code >= 300) {
      try {
        // Buffer the entire body to avoid future I/O.
        ResponseBody bufferedBody = Utils.buffer(rawBody);
        return Response.error(bufferedBody, rawResponse);
      } finally {
        rawBody.close();
      }
    }

    if (code == 204 || code == 205) {
      return Response.success(null, rawResponse);
    }

    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
      T body = serviceMethod.toResponse(catchingBody);
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
      // If the underlying source threw an exception, propagate that rather than indicating it was
      // a runtime exception.
      catchingBody.throwIfCaught();
      throw e;
    }
  }
 T toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
  }

其中 T body = serviceMethod.toResponse(catchingBody);就是将ResponseBody通过Converter转换成相应的类型

Retrofit定义好的转化器有下面几种:

Gson: com.squareup.retrofit2:converter-gson

Jackson: com.squareup.retrofit2:converter-jackson

Moshi: com.squareup.retrofit2:converter-moshi

Protobuf: com.squareup.retrofit2:converter-protobuf

Wire: com.squareup.retrofit2:converter-wire

Simple XML: com.squareup.retrofit2:converter-simplexml

Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars

其中Gson,Jackson,Moshi是用来转换Json对象的

Scalars 转换基本类型和String,eg:int,boolen,byte…

Simple XML:xml

Protobuf和Wire我还没有用过。

需要自定义的看这里:http://blog.csdn.net/lmj623565791/article/details/51304204


实践

  • GET方式请求String

    1. 创建一个接口RequsetService

      /**
       * Created by Administrator on 2016/5/4.
       */
      public interface RequsetService {
          /**
           * https://api.douban.com/v2/movie/top250?start=0&count=10
           * GET方式请求String
           */
          @GET("top250")
          Call<String> getTopMovieStr(@Query("start") int start, @Query("count") int count);
      
      }

      这里我response的类型是一个String,所以Call里面泛型为String

    2. 通过Retrofit完成上述请求
          /**
           * method: GET
           *
           * @Query response:String
           */
          private void getStrByGetMethod() {
              String baseUrl = "https://api.douban.com/v2/movie/";
              Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl).addConverterFactory(ScalarsConverterFactory.create()).build();
              RequsetService requsetService = retrofit.create(RequsetService.class);
              Call<String> call = requsetService.getTopMovieStr(0, 10);
              call.enqueue(new Callback<String>() {
                  @Override
                  public void onResponse(Call<String> call, Response<String> response) {
                      Log.e(TAG, "call:" + call.toString());
                      Log.e(TAG, "response:" + response.body());
                  }
      
                  @Override
                  public void onFailure(Call<String> call, Throwable t) {
      
                  }
              });
          }
  • GET方式请求Json
    1. 创建一个接口

          @GET("top250")
          Call<MovieEntity> getTopMovieJson(@Query("start") int start, @Query("count") int count);
    2. Retrofit完成请求
          /**
           * method: GET
           *
           * @Query response:Gson
           */
          private void getJsonByGetMethod() {
              String baseUrl = "https://api.douban.com/v2/movie/";
              Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl).addConverterFactory(GsonConverterFactory.create()).build();
              RequsetService requsetService = retrofit.create(RequsetService.class);
              Call<MovieEntity> call = requsetService.getTopMovieJson(0, 10);
              Log.e(TAG, "request:" + call.request().toString());
              call.enqueue(new Callback<MovieEntity>() {
                  @Override
                  public void onResponse(Call<MovieEntity> call, Response<MovieEntity> response) {
                      tvRequset.setText(response.body().toString());
                      Log.e(TAG, "response:" + response.body().toString());
                  }
      
                  @Override
                  public void onFailure(Call<MovieEntity> call, Throwable t) {
      
                  }
              });
          }
  • GET方式访问自签名网站https
    1. 获取自签名证书

      //未完

    2. 创建接口
      @GET
      Call<String> getHttpsHtml(@Url String url);
      
    3. Retrofit完成请求
       /**
           *  method: GET
           *  @Url
           *  response:String
           */
          private void getHttpsHtml(){
              InputStream[] inputStream = new InputStream[]{new Buffer().writeUtf8(CER_WIFI).inputStream()};
              SSLSocketFactory sslSocketFactory = HttpsUtils.getSslSocketFactory(inputStream, null, null);
      
              OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
              httpClient.sslSocketFactory(sslSocketFactory);
              OkHttpClient client = httpClient.build();
      
              String baseUrl = "https://www.wifi4.cn/wifi/yyhuang/";
              Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl).addConverterFactory(ScalarsConverterFactory.create()).client(client).build();
              RequsetService requsetService = retrofit.create(RequsetService.class);
              Call<String> call = requsetService.getHttpsHtml("BC96802F9960");
              Log.e(TAG, "request:" + call.request().toString());
              call.enqueue(new Callback<String>() {
                  @Override
                  public void onResponse(Call<String> call, Response<String> response) {
                      Log.e(TAG, "call:" + call.toString());
                      Log.e(TAG, "response:" + response.body());
                  }
      
                  @Override
                  public void onFailure(Call<String> call, Throwable t) {
                      Log.e(TAG, "onFailure call:" + call.toString());
                      Log.e(TAG, "onFailure response:" + t.toString());
                  }
              });
          }
  • POST方式请求Json(需要header情况)
    1. 创建一个接口

      @POST("login")
      Call<Object> getInfoByPost(@Body String str);

      我这里Body写成String,是因为我的数据需要加密,如果不需要加载,可以直接传对象

    2. Retrofit完成请求
       /**
           * POST
           * @Body
           */
      
          private void loginByPostMethod() {
              OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
              httpClient.addInterceptor(new Interceptor() {
                  @Override
                  public okhttp3.Response intercept(Chain chain) throws IOException {
                      Request original = chain.request();
      
                      Request request = original.newBuilder()
                              .header("ver", "V3.0.6")
                              .header("ctype", "0")
                              .method(original.method(), original.body())
                              .build();
      
                      return chain.proceed(request);
                  }
              });
      
              OkHttpClient client = httpClient.build();
              Retrofit retrofit = new Retrofit.Builder()
                      .baseUrl("http://xxxx:11203/")
                      .addConverterFactory(GsonConverterFactory.create())
                      .client(client)
                      .build();
              RequsetService requsetService = retrofit.create(RequsetService.class);
              String body = "xxx";
              Call<Object> call = requsetService.getInfoByPost(body);
              Log.e(TAG, "url:" + call.request().url());
              call.enqueue(new Callback<Object>() {
                  @Override
                  public void onResponse(Call<Object> call, Response<Object> response) {
                      // tvRequset.setText(response.body().toString());
                      Log.e(TAG, "response:" + response.body());
                  }
      
                  @Override
                  public void onFailure(Call<Object> call, Throwable t) {
      
                  }
              });
          }
      

注解

  • @Query (询问):Query 作为符号“?”,然后再将Query 的参数拼接到Url,value转换成String,null忽略。以@GET(“/list”)为例:

    1. 简单例子

       Call<ResponseBody> getListMethod(@Query(“page”) int page) 

      foo.getListMethod(1) :baseUrl /list?page=1.

    2. Array/Varargs例子
      Call<ResponseBody> getListMethod(@Query(“category”) String… categories) 

      foo.getListMethod(“bar”, “baz”) :baseUrl /list?category=bar&category=baz.

    3. encoded = true例子
       Call<ResponseBody> getListMethod(@Query(value=”foo”, encoded=true) String foo) 

      foo.getListMethod(“foo+bar”) :baseUrl /list?foo=foo+bar.

  • @Path(路径):请求的URL可以根据使用的方法替换块和参数进行动态更新。替换块是由{ 和 } 环绕的字母数字字符串构成,而相应的参数必须用 @Path 注解标注,同时要求注解的参数使用相同的字符串,以@GET(“/user/{name}”)为例:
    1. 简单例子

      Call<ResponseBody> exampleMethod(@Path(“name”) String name) 

      foo.exampleMethod(“John”) :baseUrl /user/John.

    2. encoded 例子
       Call<ResponseBody> encodedMethod(@Path(“name”) String name) 

      foo.encodedMethod(“John+Doe”) :baseUrl /user/John%2BDoe .

    3. encoded = true例子
      Call<ResponseBody> encodedMethod(@Path(value=”name”, encoded=true) String name) 

      foo.encodedMethod(“John+Doe”) :baseUrl /user/John%+Doe .

  • @QueryMap: @GET(“/search”)
    1. Call<ResponseBody> exampleMethod(@QueryMap Map<String, String> filters); 

      foo.exampleMethod(ImmutableMap.of(“foo”, “bar”, “kit”, “kat”)), baseUrl/search?foo=bar&kit=kat.

    2. Call<ResponseBody> exampleMethod(@QueryMap(encoded=true) Map<String, String> filters); 

      foo.exampleMethod(ImmutableMap.of(“foo”, “foo+bar”)), baseUrl/search?foo=foo+bar.

  • @Body: 声明一个对象当作 HTTP 请求体, @POST/PUT (“users/new”),用于POST/PUT请求
    • @POST("users/new")
      Call<User> createUser(@Body User user);
  • @FormUrlEncoded: application/x-www-form-urlencoded方式提交form-encoded 数据(表单数据),请求类似于下面这样:
    • POST http://www.example.com HTTP/1.1
      Content-Type: application/x-www-form-urlencoded;charset=utf-8
      
      title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3

      首先,Content-Type 被指定为 application/x-www-form-urlencoded;其次,提交的数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。了解其他提交方式:未完。

  • @Field: 一般用于表单的方式传递键值对,多用于POST
    1. 简单例子

      @FormUrlEncoded
      @POST("/")
      Call<ResponseBody> example(@Field("name") String name,@Field("occupation") String occupation);

      用法:foo.exampleMethod(“Bob Smith”, “President”),body:name=Bob+Smith&occupation=President.

    2. Array/Varargs例子
      @FormUrlEncoded
      @POST(“/list”)
      Call<ResponseBody> exampleMethod(@Field(“name”) String… names); 

      用法:foo.exampleMethod(“Bob Smith”, “Jane Doe”),body:name=Bob+Smith&name=Jane+Doe.

  • @FieldMap
    1. 简单例子

       @FormUrlEncoded
       @POST("/things")
       Call<ResponseBody> things(@FieldMap Map<String, String> fields); ;

      用法:foo.things(ImmutableMap.of(“foo”, “bar”, “kit”, “kat”), request body :foo=bar&kit=kat.

  • @Headers: 设置静态的 header,header 不能互相覆盖。
    •  @Headers("Cache-Control: max-age=640000")
       @GET("/")
       @Headers({
         "X-Foo: Bar",
         "X-Ping: Pong"
       })
       @GET("/")
  • @Header: 更新一个请求的 header,必须给 @Header 提供相应的参数,如果参数的值为空 header 将会被忽略.
    • @GET("/")
      
      Call<ResponseBody> foo(@Header("Accept-Language") String lang);
  • @Multipart: multipart/form-data方式提交multipart数据,请求类似于下面这样:,(上传文件)
    • POST http://www.example.com HTTP/1.1
      Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
      
      ------WebKitFormBoundaryrGKCBY7qhFd3TrwA
      Content-Disposition: form-data; name="text"
      
      title
      ------WebKitFormBoundaryrGKCBY7qhFd3TrwA
      Content-Disposition: form-data; name="file"; filename="chrome.png"
      Content-Type: image/png
      
      PNG ... content of chrome.png ...
      ------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
  • @Part: 一般用于上传文件
    • @Multipart
      
      @POST("/")
      
      Call<ResponseBody> example(@Part MultipartBody.Part photo,@Part("description") String description,@Part(value = "image", encoding = "8-bit") RequestBody image);

      eg:

      File file = new File(Environment.getExternalStorageDirectory(), "icon.png");
      RequestBody photoRequestBody = RequestBody.create(MediaType.parse("image/png"), file);
      MultipartBody.Part photo = MultipartBody.Part.createFormData("photos", "icon.png", photoRequestBody);
      Call<ResponseBody> call = example(photo, RequestBody.create(null, "abc"), photoRequestBody );
  • @PartMap: 一般用于多文件上传
    • @Multipart
      
      @POST("/upload")
      
      Call<ResponseBody> upload(@Part("file") RequestBody file,@PartMap Map<String, RequestBody> params);
      File file = new File(Environment.getExternalStorageDirectory(), "messenger_01.png");
              RequestBody photo = RequestBody.create(MediaType.parse("image/png", file);
      Map<String,RequestBody> photos = new HashMap<>();
      photos.put("photos\"; filename=\"icon.png", photo);
      photos.put("username",  RequestBody.create(null, "abc"));
      Call<ResponseBody> call = upload(null,photos);

代码以后再上传

第一次使用Retrofit,如果有什么问题或者BUG,希望能给我留言

时间: 2024-10-11 11:34:06

Retrofit2.0实践记录的相关文章

Android 基于ijkplayer+Rxjava+Rxandroid+Retrofit2.0+MVP+Material Design的android万能播放器aaa

MDPlayer万能播放器 MDPlayer,基于ijkplayer+Rxjava+Rxandroid+Retrofit2.0+MVP+Material Design的android万能播放器,可以播放本地和在线视频,可以浏览宅男杀手妹纸图片,UI设计遵循 Material Design. GitHub地址:https://github.com/Dawish/MDPlayer UI浏览:         1.UI设计: 列表使用RecyclerView,item为CardView并设置rippl

k8s1.4.3安装实践记录(2)-k8s安装

前面一篇已经安装好了ETCD.docker与flannel(k8s1.4.3安装实践记录(1)),现在可以开始安装k8s了 1.K8S 目前centos yum上的kubernetes还是1.2.0,因此我们只能是使用下载的安装包,进行kubernetes的安装 [[email protected] system]# yum list |grep kubernetes cockpit-kubernetes.x86_64 0.114-2.el7.centos extras kubernetes.x

Retrofit2.0 的初步使用

Retrofit2.0 的初步使用 首先我就不介绍了,直接说下怎么使用,本身我也是刚刚因为要仿照微软的azure-sdk-for-java(git地址是:https://github.com/Azure/azure-sdk-for-java.git) 然后去编写一个类似的程序里面就设计到了Retrofit. 我也是刚刚才使用所以说叫我讲啥原理我肯定不怎么会讲,所以这里就是告诉大家怎么使用,里面可能有些代码不怎么好,希望大家一起指出来,我会慢慢改正,请大家见谅. 首先我是把Retrofit跟OkH

Retrofit2.0+RxJava+MVP+Bmob的使用

本篇来总结一下学过的关于android方面的东西.梳理一下知识: 1.Retrofit2.0 Retrofit 是一个Square开发的类型安全的REST安卓客户端请求库.这个库为网络认证.API请求以及用OkHttp发送网络请求提供了强大的框架 . 2.RxJava/RxAndroid RxJava是一款响应式变成框架.RxAndroid在RxJava基础之上扩展了android线程调度.RxJava基本组成部分是Observables和Subscribers(事实上Observer才是最小的

ASP.NET Core 1.0 开发记录

参考页面: http://www.yuanjiaocheng.net/ASPNET-CORE/first.html http://www.yuanjiaocheng.net/ASPNET-CORE/asp-net-core-overview.html http://www.yuanjiaocheng.net/ASPNET-CORE/asp.net-core-environment.html http://www.yuanjiaocheng.net/ASPNET-CORE/newproject.h

Retrofit2.0 公共参数(固定参数)

请先阅读: Retrofit 动态参数(非固定参数.非必须参数)(Get.Post请求) 在实际项目中,对于有需要统一进行公共参数添加的网络请求,可以使用下面的代码来实现: RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint(ctx).setRequestInterceptor(new RequestInterceptor() { @Override public void intercept(RequestFacad

Retrofit2.0使用

随着Google对HttpClient 摒弃,和Volley的逐渐没落,OkHttp开始异军突起,而Retrofit则对okHttp进行了强制依赖. Retrofit是由Square公司出品的针对于Android和Java的类型安全的Http客户端, 如果看源码会发现其实质上就是对okHttp的封装,使用面向接口的方式进行网络请求,利用动态生成的代理类封装了网络接口请求的底层, 其将请求返回javaBean,对网络认证 REST API进行了很好对支持此,使用Retrofit将会极大的提高我们应

个人知识管理系统Version1.0开发记录(08)

切入点 前面,我们已经搭建好了web端的一种基本结构,需要进一步定位的主要问题有三点: 1.界面的选择和确定,用extjs做的初步样式,进一步改动为jqueryUI/html,再进一步改变为HTML5等.我们思考一种用户思维,只要有一个地方让用户不喜欢,用户就会全盘否定该款软件:所以,软件界面一定要简单.精致.能引起用户的兴趣.符合用户习惯和用户思维. 2.框架的选择和确定,struts2,hibernate/mybatis,spring等,在编写知识体核心功能模块前,需要完成选择和改写. 3.

个人知识管理系统Version1.0开发记录(04)

demo model 我们采用mvc软件架构模式,方便以后用Struts2框架技术优化.重构.封装.这次主要设计一些常用的方法工具,即数据访问逻辑.工具:eclipse.oracle.sqldeveloper. 思路如下: 1.  用sqldeveloper新建表oneds,写入一条name="cookie"的数据. 细节: 参数越多,越要细致检查单词拼写. 2.  用java读取和写入对象属性,与数据库互动. 3.  用java进行数据访问,先完成五个方法,查询所有知识点,增加知识点