Retrofit使用

Retrofit与okhttp都是Square公司出品,retrofit就是在okhttp的基础上做了一层封装。网络请求相关操作交给Okhttp处理,我们只需要通过简单的配置就能使用retrofit来进行网络请求了。

Retrofit和OkHttp关系.png

Retrofit使用入门

首先创建一个接口:

    public interface UserService {
          @GET("users/{user}/lessons")
          Call<List<Lesson>> listLessons(@Path("user") String user);
    } 

这个接口是为了通过一个url获取用户课程列表的接口,当然看着这个url地址好像也不是一个完整的能够使用的url地址,确实是这样的,Retrofit请求的地址是由两部分组成的,一部分是后面要介绍的Retrofit对象中的baseUrl和类似上面接口中的path地址共同构成的。
接下来我们是不是要定义一个实现该接口的类呢 ? 当然不是的啦。我们接下来要做的是只需构造一个Retrofit对象即可,至于原理,后面会说到。

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.test.com/")
    .build();

UserService service = retrofit.create(UserService.class);
Call<List<Lesson>> lessonCall = service.listLessons("test");
Response<List<Lesson>> result = null;
//同步调用
result = lessonCall.execute();
//异步调用
lessonCall.enqueue(new Callback<List<Lesson>>() {
            @Override
            public void onResponse(Call<List<Lesson>> call, Response<List<Lesson>> response) {
                result  = response.body();
            }

            @Override
            public void onFailure(Call<List<Lesson>> call, Throwable t) {
                t.printStackTrace();
            }
        });

这样就能轻易的调用http请求了,当然了,这只是一个小小的简单的demo,Retrofit的功能不止这些。

Retrofit使用更上一层楼

前面我们弄了一个很基本的一个例子,下面我们将更进一步使用Retrofit更多的功能。

请求类型: 我们都知道http的请求类型有GET,POST,DELETE,PUT,HEAD,PATCH 这些类型,而与之相对应的,Retrofit也包含了相对应的注解给予支持,@GET,@POST,@DELETE,@PUT,@HEAD,@PATCH 使用对应的注解即可。

请求参数:

  • @Query && @QueryMap : @Query用于http请求的单个query参数传递;@QueryMap用于多个参数传递,键值对。
  • @Field && @FieldMap : @Field 用于post请求的单个参数传递;@FieldMap用于post请求多个参数传递。
  • @Header && @HeaderMap: @Header 用于单个请求头参数;@HeaderMap用于多个请求头参数传递。
  • @Part && @PartMap:@Part用于单个文件的上传;@PartMap用于多个文件上传。
  • @Path:用于path路径变量的传递接收。
    上述示例代码:
    @GET("users/{user}/lessons")
    Call<List<Lesson>> listLessons(@Path("user") String user);

    @GET("users/getuser")
    Call<User> getUser(@Query("userId")String userId);

    @GET("users/getUserByCondition")
    Call<List<User>> getUserByCondition(@QueryMap Map<String,String> conditionMap);

    @POST("users/authorization")
    Call<User> authorization(@HeaderMap Map headerMap);
    
    @Multipart//当有文件需要上传时加入
    @POST("users/add")
    Call<User> addUser(@FieldMap Map userInfo, @Part("photo")MultipartBody.Part file);

上面这些示例都是可以直接返回对应的结果类型,但如果我们想做一个通用的Retrofit封装的http请求工具类,那就只好返回最原始的string类型,毕竟不同请求返回结果类型不同,像这样:

public interface CommonHttpService{

    @GET
    Call<String> getHttpRequest(@Url String url, @HeaderMap Map<String,String> headerMap, @QueryMap Map<String,String> queryMap);

    @FormUrlEncoded
    @POST
    Call<String> postHttpRequest(@Url String url, @HeaderMap Map<String,String> headerMap, @QueryMap Map<String,String> queryMap, @FieldMap Map<String,String> formMap);

    @POST
    Call<String> postHttpRequest(@Url String url, @HeaderMap Map<String,String> headerMap, @QueryMap Map<String,String> queryMap, @Body String body);

}

你会发现与前面的有些许不同,首先呢,@POST@GET后面没有跟上一部分path路径了,而是改由参数中的@Url String url在调用方法时传入,增加了灵活性。

Converter
如果仅仅是这样是返回不了对应的结果类型的,需要用到converter,converter的作用就是将RequestBody或ResponseBody转换为我们需要的类型,例如前面的我们想要使请求返回String类型还需要加上依赖:

        <dependency>
            <groupId>com.squareup.retrofit2</groupId>
            <artifactId>converter-scalars</artifactId>
            <version>LATEST</version>
        </dependency>

然后在构造Retrofit对象时,加上ScalarsConverterFactory的配置:

        Retrofit retrofit = new Retrofit.Builder().baseUrl("http://api.test.com")
                .addConverterFactory(ScalarsConverterFactory.create())
                .build();

ScalarsConverterFactory里面包含了对ResponseBody进行String,原始数据类型及其包装类的转换。
目前,Retrofit已经有了几个官方的converter:

//uses Gson for serialization to and from JSON
Gson: com.squareup.retrofit2:converter-gson

//uses Jackson for serialization to and from JSON
Jackson: com.squareup.retrofit2:converter-jackson

//uses Moshi for serialization to and from JSON
Moshi: com.squareup.retrofit2:converter-moshi

//A Converter which uses Protocol Buffer binary serialization
Protobuf: com.squareup.retrofit2:converter-protobuf

//A Converter which uses Wire for protocol buffer-compatible serialization.
Wire: com.squareup.retrofit2:converter-wire

//A Converter which uses Simple for XML serialization.
Simple XML: com.squareup.retrofit2:converter-simplexml

//A Converter which supports converting strings and both primitives and their boxed types to text/plain bodies.
Scalars : com.squareup.retrofit2:converter-scalars

这些converter已经能基本满足我们日常的需要了,但凡事有例外,比如我们要加密解密,要改写结果等,所以这时候就需要我们自己来写converter.我们以自定义一个 String Converter作为一个例子:

  • 自定义converter:
    先定义一个converter factory:
public class CustomStringConverterFactory extends Converter.Factory {

    public static CustomStringConverterFactory create() {
        return new CustomStringConverterFactory();
    }

    @Override
    public  Converter<ResponseBody, ?> responseBodyConverter(Type type,
     Annotation[] annotations, Retrofit retrofit) {
        if (type == String.class) {
            return new CustomStringConverter();
        }
        return null;
    }
}

这里我们只是将ResponseBody进行转换,如果你同时要将RequestBody进行转换,那就同时要覆写public Converter<?, RequestBody> requestBodyConverter(Type type,Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit)方法.

定义Converter,转换的逻辑在这里面进行:

public class CustomStringConverter implements Converter<ResponseBody, String> {

    @Override
    public String convert(ResponseBody value) throws IOException {
        return value.string();
    }
}

最后一步就是将converterfactory加入到Retrofit对象构造中使用:

Retrofit retrofit = new Retrofit.Builder().baseUrl("http://api.test.com")                .addConverterFactory(CustomStringConverterFactory.create())
.build();

好了,这样就能愉快的使用你自己定义的converter了,这里需要注意的是你如果添加的converter有多个的话小心顺序。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容