#Android# Retrofit使用指南

作者: Lshare_Blog | 来源:发表于2016-07-24 00:33 被阅读1099次

    知识框架(脑图)

    Retrofit脑图

    出现背景

    移动端网络请求复杂,代码冗余

    解决思路

    Retrofit:给Android和Java用的类型安全的HTTP客户端,将网络请求抽象成接口,以注解形式定义HTTP请求,Retrofit会自动生成对应的实现供开发人员调用。

    Retrofit设计思路

    具体步骤

    (1)添加网络访问权限并引入依赖库

    <uses-permission android:name="android.permission.INTERNET"/>
    
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    

    (2)使用注解定义网络访问的API

    public interface GitHubService {
      @GET("users/{user}/repos")
      Call<List<Repo>> listRepos(@Path("user") String user);
    }
    

    有哪些注解呢?

    • URL参数和Query参数
    • 对象到请求体的转换(eg : JSON,protocol buffers)
    • 表单提交和文件上传
    Retrofit中的注解

    (3)使用Retrofit生成该接口的一个实现

    使用Builder构建一个Retrofit,并调用Retrofit的create方法创建一个接口实现。构建的时候需要提供baseUrl,而接口定义时使用相对路径即可。

    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.github.com/")
        .addConverterFactory(GsonConverterFactory.create()) //这里使用Gson转换器,需要添加相应依赖,见问题1
        .build();
    
    GitHubService service = retrofit.create(GitHubService.class);
    

    (4)调用实现的方法来进行同步或异步的HTTP请求

    Call<List<Repo>> repos = service.listRepos("octocat");
    // 同步请求
    List<Repo> repoList = repos.execute().body();
    // 异步请求
    repos.enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
        }
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            // response.body().string();
        }
    });
    

    调用接口方法之后返回的是Call对象,可以被异步或同步执行,每个实例只能使用一次,当然可以使用clone()造一个新的来用。还可以通过cancle方法取消Call~

    在Android,回调会在主线程执行;而在JVM,回调会在发起HTTP请求的线程执行;这是自动完成的!!

    (5)进阶:操作URL

    使用替换块和方法中的参数动态地更新请求的URL。替换块的组成:用花括号包裹起来的仅含字母数字的字符串;而参数需要使用@Path注解和相同的字符串。例如:

    @GET("group/{id}/users")
    Call<List<User>> groupList(@Path("id") int groupId);
    

    也可以使用@Query注解添加查询参数,如:

    @GET("group/{id}/users")
    Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
    

    复杂点的查询参数可以结合成一个Map再用,如:

    @GET("group/{id}/users")
    Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
    

    (6)进阶:请求体

    对象可以作为HTTP的请求体(使用@Body注解),也可以使用转换器转成特定的字符串,比如JSON。

    @POST("users/new")
    Call<User> createUser(@Body User user);
    

    (7)进阶:表单提交和文件上传

    使用@FormUrlEncoded标明是表单上传的方法,然后每一个键值对使用@Field关联:

    @FormUrlEncoded
    @POST("user/edit")
    Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
    

    使用@Multipart标明是文件上传的方法,然后使用@Part分隔各个部分:

    @Multipart
    @PUT("user/photo")
    Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
    

    (8)进阶:操作请求头

    使用@Headers设置静态请求头

    @Headers("Cache-Control: max-age=640000")
    @GET("widget/list")
    Call<List<Widget>> widgetList();
    
    @Headers({
        "Accept: application/vnd.github.v3.full+json",
        "User-Agent: Retrofit-Sample-App"
    })
    @GET("users/{username}")
    Call<User> getUser(@Path("username") String username);
    

    注意:请求头不会相互覆盖,同名的请求头会被保留进请求。

    可以使用@Header动态修改请求头,如果值是null,那么该头部会被清除;还有toString方法会被调用。

    @GET("user")
    Call<User> getUser(@Header("Authorization") String authorization)
    

    (9)进阶:Retrofit配置转换器

    为什么要配置转换器?

    Retrofit已经不提供给默认的转换器了,需要相应的转换器,比如要用Gson解析的话就需要添加依赖并使用addConverterFactory方法在构建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

    怎么添加转换器?

    使用addConverterFactory方法

    // 以添加GsonConverterFactory为例
    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.github.com")
        .addConverterFactory(GsonConverterFactory.create())
        .build();
    
    GitHubService service = retrofit.create(GitHubService.class);
    

    Q&A

    问题1:IllegalArgumentException: Unable to create converter for class...

    Retrofit已经不提供给默认的转换器了,需要相应的转换器比如要用Gson解析的话就需要添加依赖:

    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    

    然后构建Retrofit时使用该转换器:

    Retrofit client = new Retrofit.Builder()
    .baseUrl("https://github.com")
    .addConverterFactory(GsonConverterFactory.create())
    .build();
    

    值得注意的是:JSON Converter要放置在最后,因为没有确切的条件可以判定一个对象是否是JSON对象

    参考文档

    1. Retrofit
    2. 用Retrofit2简化HTTP请求
    3. Unable to create converter for java.util.List Retrofit 2.0.0-beta2
    4. Retrofit请求参数注解字段说明

    相关文章

      网友评论

      • Serven_:服务端对请求头和请求体进行了加密,我们Android这边需要怎么处理呢
        Lshare_Blog: @Serven_ 按照加密算法加密,然后发出请求不就行了吗?这个只要是网络请求,总是要符合协议的,path 加密,你就封装一个加密方法然后在用@path ,field 也同理
        Serven_:@扫地僧林怀民 是加密啊,就是请求头和请求体进行加密
        Lshare_Blog:@Serven_ 先获取数据,然后进行解密
      • fbcde8a99e17:retrofit2好像还有点不一样,不过大体上差不多
        Lshare_Blog:@spy_dev 我用的就是retrofit2,是哪里有问题吗?
      • 捡淑:全文看中了那张表
        Lshare_Blog:@捡淑 可怕

      本文标题:#Android# Retrofit使用指南

      本文链接:https://www.haomeiwen.com/subject/dlbwjttx.html