Android之网络请求8————Retrofit的简单使用

文章目录

  • Android之网络请求8————Retrofit的简单使用
      • 一.Retrofit的介绍
      • 二.Retrofit的简单使用
      • 三.Retrofit的注解
        • 1.概述
        • 2.网络请求方法
        • 3.标记类
        • 4.网络请求参数
      • 四.Retrofit的数据解析器和网络请求适配器
        • 1.数据解析器
        • 2.网络请求适配器
      • 五.Retrofit和GSON
        • 1.步骤a:添加Retrofit库的依赖
        • 2.步骤b:创建 接收服务器返回数据 的类
        • 3.步骤c:创建 用于描述网络请求 的接口
        • 4.步骤d:进行网络请求
        • 5.运行结果
      • 六.Retrofit和Rxjava的结合
        • 1.步骤a:添加Retrofit库的依赖
        • 2.步骤b:创建 接收服务器返回数据 的类
        • 3.步骤c:创建 用于描述网络请求 的接口
        • 4.步骤d:进行网络请求
        • 5.运行结果
      • 七.参考资料
      • 八.文章索引

一.Retrofit的介绍

Retreofit是什么,根据其官方文档的介绍,他就是一个适用于 Android 和 Java 的类型安全的 HTTP 客户端。特别说明Retrofit网络请求本质是有OkHttp完成的,而Retrofit仅负责网络请求接口的封装。

Android之网络请求9————Retrofit的简单使用_第1张图片

二.Retrofit的简单使用

Retrofit的简单使用我们先从请求百度URL开始
步骤1:
添加第三方库依赖

    compile 'com.squareup.retrofit2:retrofit:2.4.0'    compile 'com.squareup.retrofit2:converter-scalars:2.3.0'

步骤2:
添加权限

   <uses-permission android:name="android.permission.INTERNET"/>

步骤3:
创建用于描述请求的接口

public interface BaiduInterface {    //@GET指定请求方法,        @GET    Call<String> baidu(@Url String url);}

步骤4:
进行请求

        //a.创建Retrofit对象        Retrofit retrofit = new Retrofit.Builder()                //指定baseurl,这里有坑,最后后缀出带着“/”                .baseUrl("http://www.baidu.com/")                //设置内容格式,这种对应的数据返回值是String类型                .addConverterFactory(ScalarsConverterFactory.create())                //定义client类型                .client(new OkHttpClient())                //创建                .build();        //b,获得定义的接口的实例        BaiduInterface baiduInterface = retrofit.create(BaiduInterface.class);        //配置参数        Call<String> baidu = baiduInterface.baidu("http://www.baidu.com");        //c.执行异步请求        baidu.enqueue(new Callback<String>() {            @Override            public void onResponse(Call<String> call, Response<String> response) {                Log.d("1111", "onResponse: "+response.body());            }            @Override            public void onFailure(Call<String> call, Throwable t) {                Log.d("1111", "onResponse: "+t);            }        });

请求结果:
在这里插入图片描述

三.Retrofit的注解

上面我们简单使用了Retrofit请求了百度的。对Retrofit的使用有了简单的了解,在上面的代码中,出现了@GET和@URL,可以看出Retrofit大量使用了注解,对请求进行了封装,我们继续来看Retrofit中使用的注解。

1.概述

在Retrofit中,注解的使用都在定义的接口中,分为3类:即网络请求方法,标记类,网络请求参数。
Android之网络请求9————Retrofit的简单使用_第2张图片

2.网络请求方法

网络请求方法如下:

可以看出来这些都是Http的方法,我们一般常用的就是GET和POST

具体说明:
a. @GET、@POST、@PUT、@DELETE、@HEAD
以上方法分别对应 HTTP中的网络请求方式

每个注解后面都可以设置一个URL,也可以不设置

public interface RetrofitInterface {    @GET("https://www.baidu.com")    Call<String> baidu();    //@GE作用:采用Get方法发送请求    //Call String是请求返回数据的格式,可以是String,也可以是json,也可是GSON。    //baidu() 即进行请求的方法    //关于URL部分,在下面有教详细的讲解}

[email protected]
作用:替换@GET、@POST、@PUT、@DELETE、@HEAD注解的作用 及 更多功能拓展
具体使用:通过属性method、path、hasBody进行设置

public interface RetrofitInterface {   /**     * method:网络请求的方法(区分大小写)     * path:网络请求地址路径     * hasBody:是否有请求体     */    @HTTP(method = "GET", path ="https://www.baidu.com", hasBody = false)    Call<ResponseBody> getCall(@Path("id") int id);    // method 的值 retrofit 不会做处理,所以要自行保证准确}

c.关于URL
Retrofit将URL分为两部分,一部分在请求接口的注解后,一部分在Retrofit的baseUrl中。即

// 第1部分:在网络请求接口的注解设置 @GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")Call<Translation>  getCall();// 第2部分:在创建Retrofit实例时通过.baseUrl()设置Retrofit retrofit = new Retrofit.Builder()                .baseUrl("http://fanyi.youdao.com/") //设置网络请求的Url地址                .addConverterFactory(GsonConverterFactory.create()) //设置数据解析器                .build();

网络请求的完整 Url =在创建Retrofit实例时通过.baseUrl()设置 +网络请求接口的注解设置(下面称 “path“ )
具体整合规则

path的URL还可以使用替换块

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

同时网络请求参数@URL也可以设置URL

public interface RetrofitInterface {    @GET    Call<String> baidu(@Url String url);}

3.标记类


a.FormUrlEncoded

  • 作用:表示发送form-encoded的数据
  • 注意:每个键值对都需要用@Filed来注解键名,随后的对象需要提供值。

定义接口方法

public interface RetrofitInterface {    /**     *表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)     * Field("username") 表示将后面的 String name 中name的取值作为 username 的值     */    @POST("/form")    @FormUrlEncoded    Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);}

b.Multipart

  • 作用:表示发送form-encoded的数据(适用于 有文件 上传的场景)
  • 注意:每个键值对都需要用@part来注解键名,随后对象需要提供值
public interface RetrofitInterface {    /**     * {@link Part} 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型     * 除 {@link okhttp3.MultipartBody.Part} 以外,     * 其它类型都必须带上表单字段({@link okhttp3.MultipartBody.Part} 中已经包含了表单字段的信息),     */    @POST("/form")    @Multipart    Call<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);}

[email protected]

  • 作用:表示返回的数据以流的形式返回,场用于大文件传输的场景
  • 注意:url由于是可变的,因此用 @URL 注解符号来进行指定,大文件官方建议用 @Streaming 来进行注解,不然会出现IO异常,小文件可以忽略不注入。如果想进行断点续传的话 可以在此加入header
public interface ApiService {  @Streaming  @GET  Observable<ResponseBody> downloadFile(@Url String   fileUrl);}

4.网络请求参数

[email protected] & @Headers

  • 作用:添加请求头
    具体使用:
// @Header@GET("user")Call<User> getUser(@Header("Authorization") String authorization)// @Headers@Headers("Authorization: authorization")@GET("user")Call<User> getUser()// 以上的效果是一致的。// 区别在于使用场景和使用方式// 1. 使用场景:@Header用于添加不固定的请求头,@Headers用于添加固定的请求头// 2. 使用方式:@Header作用于方法的参数;@Headers作用于方法

[email protected]

  • 作用:以Post方式传递自定义数据类型给服务器
  • 注意: 如果提交的是一个Map,那么作用相当于@Field,不过Map要经过FormBody.Builder 类处理成为符合 Okhttp 格式的表单,如:
FormBody.Builder builder = new FormBody.Builder();builder.add("key","value");

c.Field&FieldMap

  • 作用:发送 Post请求 时提交请求的表单字段
  • 注意:与 @FormUrlEncoded 注解配合使用
    Field的使用
public interface RetrofitInterface {    /**     *表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)     * Field("username") 表示将后面的 String name 中name的取值作为 username 的值     */    @POST("/form")    @FormUrlEncoded    Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age)}//具体使用 Call<ResponseBody> call1 = service.testFormUrlEncoded1("Carson", 24);

FieldMap的使用

public interface RetrofitInterface {    /**     *表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)     * Field("username") 表示将后面的 String name 中name的取值作为 username 的值     */    @POST("/form")    @FormUrlEncoded    Call<ResponseBody>testFormUrlEncoded2(@FieldMap Map<String, Object> map);}//具体使用   Map<String, Object> map = new HashMap<>();   map.put("username", "Carson");   map.put("age", 24);   Call<ResponseBody> call2 = service.testFormUrlEncoded2(map);

[email protected] & @PartMap

  • 作用:发送的Post请求时提交的表单字段
  • 注意:与 @Multipart 注解配合使用
  • 与@Field的区别:功能相同,但携带的参数类型更加丰富,包括数据流,所以适用于 有文件上传 的场景

@Part的使用

public interface RetrofitInterface {        /**         * {@link Part} 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型         * 除 {@link okhttp3.MultipartBody.Part} 以外,其它类型都必须带上表单字段({@link okhttp3.MultipartBody.Part} 中已经包含了表单字段的信息),         */        @POST("/form")        @Multipart        Call<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);}        MediaType textType = MediaType.parse("text/plain");        RequestBody name = RequestBody.create(textType, "Carson");        RequestBody age = RequestBody.create(textType, "24");        RequestBody file = RequestBody.create(MediaType.parse("application/octet-stream"), "这里是模拟文件的内容");//调用        MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", "test.txt", file);        Call<ResponseBody> call3 = service.testFileUpload1(name, age, filePart);        ResponseBodyPrinter.printResponseBody(call3);

@PartMap的使用

public interface RetrofitInterface {           /**         * PartMap 注解支持一个Map作为参数,支持 {@link RequestBody } 类型,         * 如果有其它的类型,会被{@link retrofit2.Converter}转换,如后面会介绍的 使用{@link com.google.gson.Gson} 的 {@link retrofit2.converter.gson.GsonRequestBodyConverter}         * 所以{@link MultipartBody.Part} 就不适用了,所以文件只能用 @Part MultipartBody.Part          */        @POST("/form")        @Multipart        Call<ResponseBody> testFileUpload2(@PartMap Map<String, RequestBody> args, @Part MultipartBody.Part file);}        MediaType textType = MediaType.parse("text/plain");        RequestBody name = RequestBody.create(textType, "Carson");        RequestBody age = RequestBody.create(textType, "24");        RequestBody file = RequestBody.create(MediaType.parse("application/octet-stream"), "这里是模拟文件的内容");//调用        Map<String, RequestBody> fileUpload2Args = new HashMap<>();        fileUpload2Args.put("name", name);        fileUpload2Args.put("age", age);        //这里并不会被当成文件,因为没有文件名(包含在Content-Disposition请求头中),但上面的 filePart 有        //fileUpload2Args.put("file", file);        Call<ResponseBody> call4 = service.testFileUpload2(fileUpload2Args, filePart); //单独处理文件        ResponseBodyPrinter.printResponseBody(call4);

[email protected]和@QueryMap

  • 作用:用于 @GET 方法的查询参数(Query = Url 中 ‘?’ 后面的 key-value)
  • 使用:和上面的两个相同

f. @Path

  • 作用:URL的省缺值
@GET("group/{id}/users")Call<List<User>> groupList(@Path("id") int groupId);

[email protected]

  • 作用:直接传入一个请求的URL变量
  • 具体使用
public interface RetrofitInterface {    @GET    Call<String> baidu(@Url String url);}

四.Retrofit的数据解析器和网络请求适配器

在上面的请求百度的例子中,我们使用了ScalarsConverterFactory.create()作为数据的解析器,同时Retrofit也支持多种网络请求适配器方式,比如:guava、Java8和rxjava

数据解析器和网络请求的适配器的添加发生在创建 Retrofit 实例

Retrofit retrofit = new Retrofit.Builder()                .addConverterFactory(GsonConverterFactory.create()) // 设置数据解析器                .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 支持RxJava平台                .build();

1.数据解析器

Retrofit支持多种数据解析器,如下:

数据解析器 Gradle依赖
Gson com.squareup.retrofit2:converter-gson:2.0.2
Jackson com.squareup.retrofit2:converter-jackson:2.0.2
Simple XML com.squareup.retrofit2:converter-simplexml:2.0.2
Protobuf com.squareup.retrofit2:converter-protobuf:2.0.2
Moshi com.squareup.retrofit2:converter-moshi:2.0.2
Wire com.squareup.retrofit2:converter-wire:2.0.2
Scalars com.squareup.retrofit2:converter-scalars:2.0.2

2.网络请求适配器

Retrofit支持多种网络请求适配器方式:guava、Java8和rxjava.
使用时如使用的是 Android 默认的 CallAdapter,则不需要添加网络请求适配器的依赖
需要在Gradle添加依赖:

网络请求适配器 Gradle依赖
guava com.squareup.retrofit2:adapter-guava:2.0.2
Java8 com.squareup.retrofit2:adapter-java8:2.0.2
rxjava com.squareup.retrofit2:adapter-rxjava:2.0.2

五.Retrofit和GSON

以豆瓣电影上映接口的请求为例:
API接口
请求URL:
Android之网络请求9————Retrofit的简单使用_第3张图片
返回的JSON数据(详细内容可查看链接):
Android之网络请求9————Retrofit的简单使用_第4张图片
具体实现:

1.步骤a:添加Retrofit库的依赖

添加Retrofit和GSON的依赖

    compile 'com.squareup.retrofit2:retrofit:2.4.0'    compile 'com.squareup.retrofit2:converter-gson:2.4.0'

添加权限

   <uses-permission android:name="android.permission.INTERNET"/>

2.步骤b:创建 接收服务器返回数据 的类

这里只接收了部分数据

public class Theaters {    private int count; //返回数量    private int start; //分页量    private int total; //数据库总数量    @SerializedName("subjects")    private List<Subjects> data; //电影的具体信息    private class Subjects {        private String title;//电影名        private String mainland_pubdate;//大陆上映时间        private String alt;//网页连接    }    //定义 输出返回数据 的方法    public void show() {        Log.d("返回数量", ""+count);        Log.d("分页量", ""+start);        Log.d("数据库总数量", ""+total);        for (Subjects subjects: data){            Log.d("电影名", ""+subjects.title);            Log.d("大陆上映时间", ""+subjects.mainland_pubdate);            Log.d("网页连接", ""+subjects.alt);        }    }}

3.步骤c:创建 用于描述网络请求 的接口

public interface RetrofitInterface {    @GET("in_theaters")    Call<Theaters> theaters(@QueryMap Map<String ,Object>map);}

4.步骤d:进行网络请求

        //a.创建Retrofit对象        Retrofit retrofit = new Retrofit.Builder()                //指定baseurl,这里有坑,最后后缀出带着“/”                .baseUrl("https://api.douban.com/v2/movie/")                //设置内容格式,这种对应的数据返回值是String类型                .addConverterFactory(GsonConverterFactory.create())                //创建                .build();        //b,获得定义的接口的实例        RetrofitInterface retrofitInterface = retrofit.create(RetrofitInterface.class);        // 实现的效果与上面相同,但要传入Map        Map<String, Object> map = new HashMap<>();        map.put("apikey", "0b2bdeda43b5688921839c8ecb20399b");        map.put("start",0);        map.put("count", 100);        //配置参数        Call<Theaters> call =  retrofitInterface.theaters(map);        //c.进行网络请求        call.enqueue(new Callback<Theaters>() {            //请求成功时回调            @Override            public void onResponse(Call<Theaters> call, Response<Theaters> response) {                // 处理返回的数据结果                response.body().show();            }            //请求失败时回调            @Override            public void onFailure(Call<Theaters> call, Throwable throwable) {                Log.e("retrofit", "onFailure: "+throwable);            }        });

5.运行结果

Android之网络请求9————Retrofit的简单使用_第5张图片

六.Retrofit和Rxjava的结合

还是以上面的接口为例:关于Rxjava更多详细的内容可以参看我之前的博客Android之Rxjava2.X 1————Rxjava概述

API接口同上

1.步骤a:添加Retrofit库的依赖

添加Retrofit和GSON的依赖

    // Android 支持 Rxjava    // 此处一定要注意使用RxJava2的版本    compile 'io.reactivex.rxjava2:rxjava:2.1.7'    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'    // Android 支持 Retrofit    compile 'com.squareup.retrofit2:retrofit:2.4.0'    // 衔接 Retrofit & RxJava    // 此处一定要注意使用RxJava2的版本    compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'    // 支持Gson解析    compile 'com.squareup.retrofit2:converter-gson:2.4.0'

添加权限

   <uses-permission android:name="android.permission.INTERNET"/>

2.步骤b:创建 接收服务器返回数据 的类

这里只接收了部分数据

public class Theaters {    private int count; //返回数量    private int start; //分页量    private int total; //数据库总数量    @SerializedName("subjects")    private List<Subjects> data; //电影的具体信息    private class Subjects {        private String title;//电影名        private String mainland_pubdate;//大陆上映时间        private String alt;//网页连接    }    //定义 输出返回数据 的方法    public void show() {        Log.d("返回数量", ""+count);        Log.d("分页量", ""+start);        Log.d("数据库总数量", ""+total);        for (Subjects subjects: data){            Log.d("电影名", ""+subjects.title);            Log.d("大陆上映时间", ""+subjects.mainland_pubdate);            Log.d("网页连接", ""+subjects.alt);        }    }}

3.步骤c:创建 用于描述网络请求 的接口

public interface RetrofitInterface {    @GET("in_theaters")    Observable<Theaters> theaters2(@QueryMap Map<String ,Object>map);}

4.步骤d:进行网络请求

   //a.创建Retrofit对象        Retrofit retrofit = new Retrofit.Builder()                //指定baseurl,这里有坑,最后后缀出带着“/”                .baseUrl("https://api.douban.com/v2/movie/")                //设置内容格式,这种对应的数据返回值是String类型                .addConverterFactory(GsonConverterFactory.create())                .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支持RxJava                //创建                .build();        //b,获得定义的接口的实例        RetrofitInterface retrofitInterface = retrofit.create(RetrofitInterface.class);        // 实现的效果与上面相同,但要传入Map        Map<String, Object> map = new HashMap<>();        map.put("apikey", "0b2bdeda43b5688921839c8ecb20399b");        map.put("start", 0);        map.put("count", 100);        //配置参数        Observable<Theaters> observable = retrofitInterface.theaters2(map);        //c. 通过Rxjava进行网络请求        observable.subscribeOn(Schedulers.io()) // 切换到IO线程进行网络请求                .observeOn(AndroidSchedulers.mainThread()) // 切换回到主线程 处理请求结果                .subscribe(new Observer<Theaters>() {                    @Override                    public void onSubscribe(Disposable d) {                    }                    @Override                    public void onNext(Theaters result) { // e.接收服务器返回的数据                        result.show();                    }                    @Override                    public void onError(Throwable e) {                        Log.d("Retrofit", "请求失败");                    }                    @Override                    public void onComplete() {                    }                });

5.运行结果

https://www.jianshu.com/p/0fda3132cf98Android之网络请求9————Retrofit的简单使用_第6张图片

七.参考资料

这是一份很详细的 Retrofit 2.0 使用教程
网络加载框架 - Retrofit
Retrofit 官方文档翻译

八.文章索引

Android之网络请求1————HTTP协议
Android之网络请求2————OkHttp的基本使用
Android之网络请求3————OkHttp的拦截器和封装
Android之网络请求4————OkHttp源码1:框架
Android之网络请求5————OkHttp源码2:发送请求
Android之网络请求6————OkHttp源码3:拦截器链
Android之网络请求7————OkHttp源码4:网络操作
Android之网络请求8————OkHttp源码5:缓存相关
Android之网络请求9————Retrofit的简单使用
Android之网络请求10————Retrofit的进阶使用
Android之网络请求11————Retrofit的源码分析

更多相关文章

  1. Android中数据存储——文件存储数据
  2. 在android中使用Post方式提交数据
  3. android 网络交互
  4. 深入探究Android的WebView下载网络文件的盗链问题
  5. Android与服务器端数据交互
  6. Android 数据库批量查询数据的操作
  7. Android中ListView分页加载数据

随机推荐

  1. Python实现LRFM模型分析客户价值
  2. Android(安卓)高手进阶教程(十四)之----A
  3. Python数据分析实战:获取数据
  4. 关于学习时间的一点小感悟
  5. 什么能力很重要,但大多数人却没有?
  6. 泰坦尼克号数据分析
  7. 最全总结!聊聊 Python 操作PDF的几种方法(
  8. 聊聊职业规划,怀疑人生的那种!
  9. 年轻人,请别再乱花钱了!
  10. 同伴压力,大学生一定摆脱这种思维