Android体系课学习 之 网络请求库Retrofit使用方式(附Demo)

简介: - 网络请求在我们开发中起的很大比重,有一个好的网络框架可以节省我们的开发工作量,也可以避免一些在开发中不该出现的bug- Retrofit是一个轻量级框架,基于OkHttp的一个Restful框架

前言

  • 网络请求在我们开发中起的很大比重,有一个好的网络框架可以节省我们的开发工作量,也可以避免一些在开发中不该出现的bug
  • Retrofit是一个轻量级框架,基于OkHttp的一个Restful框架

微信图片_20220527220425.png

**今天我们来看下Retrofit的具体使用方式**

[Android体系课学习 之 网络请求库OkHttp使用方式(附Demo)]()

[Android体系课学习 之 网络请求库OkHttp看这一篇就够了]()

Android体系课学习 之 网络请求库Retrofit使用方式(附Demo)

Android体系课学习 之 网络请求库Retrofit源码分析

[Android体系课学习 之 RxJava看这篇就够了]()

[Android体系课学习 之 RxJava操作符详解]()

[Android体系课学习 之 RxJava源码分析]()

1.目录

Retrofit 2.0目录介绍.png

2.简介

  • 功能

    • 使用接口方法注解的方式配置网络请求参数
  • 优点

    • 功能强大:支持同步和异步,支持自定义数据解析类型,常用如Json
    • 支持多平台,如Android,Java8等
    • 使用简单:通过注释的方式动态配置交易请求参数
    • 使用多种设计模式,对模块之间解耦,拓展性好
    • 目前最新版本支持协程的方式进行网络请求,不需要再指定使用同步还是异步方式
  • 使用场景

    支持所有的网络请求场景,特别是请求次数比较频繁的场景,因为内部是基于OkHttp,而OkHttp内部使用了各种拦截器,且对请求有做缓存IO复用操作,防止短时间重复连接操作,浪费资源。
需要注意:Retrofit请求的本质是通过OkHttp发送网路请求,而Retrofit只是负责网络前期接口的封装

retrofit网络流程.png

3.使用教程

Retrofit使用步骤如下:

  • 步骤1:添加Retrofit库依赖
  • 步骤2:根据服务器响应格式创建响应类
  • 步骤3:创建网络请求接口并添加注解
  • 步骤4:创建Retrofit实例
  • 步骤5:创建网络请求实例
  • 步骤6:调用网络请求方法
  • 步骤7:处理网络请求返回

步骤1:添加Retrofit库依赖

在模块的build.gradle中添加

   implementation 'com.squareup.retrofit2:retrofit:2.9.0' 
   implementation 'com.squareup.retrofit2:converter-gson:2.0.2'

在manfest中添加网络权限

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

步骤2: 根据服务器响应格式创建响应类、

假如服务器给了以下请求响应格式:对应了Translation这个响应类,

一个使用中括号括起来的数据格式代表一个新的类:如格式中的message,baesInfo等由于是另起一个中括号,所以需要创建一个内部类

{
    "status" :1,
    “message”:{    
            “baesInfo”:{
                    “from”:“eng”
                    “to” : “CN”
                    “translate_result”:“hello”
            }
            “word_name”:“你好”
    }
}
/**
 * 创建解析类
 */
public class Translation {
    private int status;
    private message message;
    private static class message {
        private baesInfo baesInfo;
        private String word_name;
    }
    private static class baesInfo {
        private String from;
        private String to;
        private String translate_result;
    }
}

步骤3: 创建网络请求接口并添加注解

Retrofit将网络请求抽象成一个接口,并使用注解的方式配置网络请求参数和方法

1.用 动态代理的方式将请求解析为一个Http请求,并执行这个请求

2.接口中每个方法的参数都需要使用注释的方式完成。

/**  

* 创建用于描述网络请求的接口  
  */  
  public interface RequestInterface{  
   @GET("/dictionary/word/query/v2?client=1&timestamp=1637143127&isChangeTo=0&sign=63243e0fb77fa81e&uuid=d6ceb7789ff04ff69355cea0a3325e40&sv=android10&v=11.1.7&uid=&translateType=-1&key=1000001&identity=12&word=%25E4%25BD%25A0%25E5%25A5%25BD%25E5%25B0%258F%25E5%25A7%2590&signature=7cdc8cee1566bde7c34a817fbab31a20")  
   Call<Translation> getCall();  
   // 注解里传入 网络请求 的部分URL地址  
   // Retrofit把网络请求的URL分成了两部分:一部分放在Retrofit对象里,另一部分放在网络请求接口里  
   // 如果接口里的url是一个完整的网址,那么放在Retrofit对象里的URL可以忽略  
   // getCall()是接受网络请求数据的方法  
  }
注解详细说明:
第一类:网络请求方法注释
类型 名称 解释
请求方法 @GET,@POST ,@PUT,@DELETE,@PATH,@HEAD,@OPTIONS 所有请求都对应一个网络请求方法,接收一个URL地址,如果设置了baseUrl,则完整地址= baseUrl+这里设置的url
@HTTP 替换以上七个注解

这里对URL地址组成做个详细说明:

  • 网络请求完整url = 创建Retrofit的时候设置的baseUrl+网络请求接口注解设置的路径path
如果path是一个完整路径,则无需再配置baseUrl,否则会报错

来讲下HTTP注释

  • HTTP注释主要是用来取代之前请求方式GET,POST等的操作,扩展性更强
  • 如下面这个调用方式:

    下面的例子使用HTTP取代POST方式,并在path中传递一个参数,来动态配置url

public interface RequestInterface {  
    /**  
     * method:请求方式  
     * path:请求路径 {user}:表示需要从参数中传入  
     * hasBody:请求体是否存在  
     * @param user  
     * @return  
     */  
    @HTTP(method = "POST",path = "select/{user}",hasBody = false)  
    Call<Translation> getCall(@Path("user") int user);  

}
第二类:网络请求标记注释

标记类注释主要包括三个:

  • @FormUrlEncoded:表示请求体是一个form表单

    每个键值对以Field的形式传入

    使用方式如下:

        /**
        * FormUrlEncoded:表示该请求体是一个表单格式(Content-Type:application/x-www-form-urlencoded)
        * @Field ("userName") String name:表示以userName为key,以name为值的表单数据
        * */
        @HTTP(method = "POST",path = "select/{user}",hasBody = false)
        @FormUrlEncoded
        Call<Translation> showFULAnnotation(@Field ("userName") String name,@Field ("pwd") String pwd,@Path("user") int user);
    具体调用:  
        RequestInterface rq = retrofit.create(RequestInterface.class);
        Call<Translation> call1 = rq.showFULAnnotation("name","123456",123);
  • @Multipart:表示请求实体是一个form,适用于有文件上传的场景

    每个键值对以Part形式传入

    使用方式如下:

    /**
         * Multipart:表示该请求体是一个表单格式(Content-Type:application/x-www-form-urlencoded),且支持文件上传
         * @Part ("userName") String name:表示以userName为key,以name为值的表单数据
         * @Par MultipartBody.Part file ,表示fileText是一个Part,内部包含了一个key和body
         * Part后面可以是:RequestBody或者MultipartBody.Part
         * */
        @HTTP(method = "POST",path = "select/{user}",hasBody = false)
        @Multipart
        Call<Translation> showMultipart(@Part("userName") RequestBody name,
                                        @Part ("pwd") RequestBody pwd,
                                        @Part MultipartBody.Part fileText ,
                                        @Path("user") int user);
    
    //调用处:
    RequestInterface rq1 = retrofit.create(RequestInterface.class);
    RequestBody bodyName = RequestBody.create(MediaType.get("text/plain"),"yuhb");
    RequestBody bodyPwd = RequestBody.create(MediaType.get("text/plain"),"123");
    //这里获取文件系统中的数据,并传给MultipartBody.Part
    File file = new File("/aa/bb/file.png");
    RequestBody bodyFile = RequestBody.create(MediaType.get("image/png"),file);
    MultipartBody.Part part = MultipartBody.Part.createFormData("MyFile","testFile.text",bodyFile);
    rq1.showMultipart(bodyName,bodyPwd,part,123);
  • @Streaming:适用于一些返回数据量比较大的场景,如下载大数据等,并且以流的形式返回
第三类:网络请求参数注解

a)@Header和@Headers

定义:设置请求头

**两者区别:**
  • Headers添加的是固定的头而Header是添加不固定的头
  • Headers作用在方法上,而Header作用在参数上

    使用方式如下:

    /**
         *这里使用Header注解参数动态传入Header数据,可以设置多个Header
         */
        @GET("/get")
        Call<Translation> showHeader(@Header("Content") String content);
    
        /**
         *这里使用Headers注解方法设置头数据,只能设置一次
         */
        @Headers("Content:content")
        @GET("/get")
        Call<Translation> showHeaders();

b)@Body

定义:传入一个对象作为Body传入参数,作为POST的请求body
作用类似于FieldMap

使用方式如下:

/**
     *这里使用Body注解修饰了一个Bean对象,
     */
    @POST("/post")
    Call<Translation> showBody(@Body Bean bean);

    //这里调用:
    rq1.showBody(new Bean("yuhb","28","love you"));

步骤4:创建Retrofit实例

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://dict.iciba.com/") // 设置 网络请求 Url
                .addConverterFactory(GsonConverterFactory.create()) //设置使用Gson解析(记得加入依赖            )
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 支持RxJava平台             
                .build();
a 关于数据解析器
  • Retrofit支持多种数据解析方式
  • 需要在项目build.gradle中添加对应依赖

    常用的是Gson解析器:

    implementation 'com.squareup.retrofit2:converter-gson:2.0.2' 
b 关于网络适配器
Retrofit支持多种适配器
使用时如使用的是 Android 默认的 CallAdapter,则不需要添加网络请求适配器的依赖,否则则需要按照需求进行添加\
Retrofit 提供的 CallAdapter

步骤5:创建网络请求实例

GetRequest_Interface request = retrofit.create(RequestInterface.class);
Call<Translation> call = request.getCall();

步骤6:调用网络请求方法

这里使用了异步的方式,还可以使用同步的方式,同步会阻塞线程,所以切记在主线程上调用同步的方式

//异步调用
call.enqueue(new Callback<Translation>() {
            //请求成功时回调
            @Override
            public void onResponse(Call<Translation> call, Response<Translation> response) {
                // 步骤7:处理返回的数据结果
                response.body().show();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(RetrofitTestActivity.this,""+response.body().getResult(),Toast.LENGTH_SHORT).show();
                    }
                });
            }

            //请求失败时回调
            @Override
            public void onFailure(Call<Translation> call, Throwable throwable) {
                System.out.println("连接失败");
            }
        });
//同步调用
call.execute();

4.项目实战

  • 首先我们使用ApiPost 的mock server功能mock出一个登录api接口

mockserver.png

接口类型:POST

mock服务器地址:

https://console-mock.apipost.cn/app/mock/project/a050bb0d-28d9-48fd-c7db-b2953f7f1caf/api/demo/login

响应数据格式:

{
    "code": "0000",
    "data": {
        "verifySuccess": true,
        "userInfo": {
            "username": "admin",
            "email": "t.opfmyej@hkhygiel.lv",
            "address": "@address"
        }
    },
    "desc": "成功"
}
  • 步骤1:根据响应数据格式,我们创建响应数据转换类:
每个中括号代表一个类
/**
*响应数据类
* */
public class Result{
    String code;
    Data data;
    class Data{
        boolean verifySuccess;
        UserInfo userInfo;

        @Override
        public String toString() {
            return "Data{" +
                    "verifySuccess=" + verifySuccess +
                    ", userInfo=" + userInfo +
                    '}';
        }

        class UserInfo{
            String username;
            String email;
            String address;

            @Override
            public String toString() {
                return "UserInfo{" +
                        "username='" + username + ''' +
                        ", email='" + email + ''' +
                        ", address='" + address + ''' +
                        '}';
            }
        }

    }

    @Override
    public String toString() {
        return "Result{" +
                "code='" + code + ''' +
                ", data=" + data +
                '}';
    }
}

请求api:

请求接口.png

步骤2:根据请求api创建请求接口类

public interface RequestInterface {
    /**
     * FormUrlEncoded:只是请求Body为一个Form表单
     **/
    @FormUrlEncoded
    @POST("api/demo/login")
    Call<Result> login(@FieldMap Map<String, Object> map);

    /**
     * FormUrlEncoded:只是请求Body为一个Form表单
     **/
    @FormUrlEncoded
    @POST("api/demo/login")
    Call<Result> login(@Field("username") String username,
                       @Field("password") String password,
                       @Field("mobile") String mobile,
                       @Field("ver_code") String ver_code);
}

请求方法:POST
请求URL:这里使用baseUrl+url路径(api/demo/login)
请求接口:使用了@Field和@FieldMap两种模式,在参数比较多的情况下,应该使用@FieldMap的注解表示参数输入

调用了FormUrlEncoded表示该请求实体是一个表单。

步骤3:创建Retrofit实例
1.设置baseUrl
2.设置GsonConverterFactory数据解析器;

记得添加依赖:

implementation com.squareup.retrofit2:converter-gson:2.0.9
Retrofit retrofit =  new Retrofit.Builder().baseUrl("https://console-mock.apipost.cn/app/mock/project/a050bb0d-28d9-48fd-c7db-b2953f7f1caf/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();

步骤4:获取请求代理类

RequestInterface request = retrofit.create(RequestInterface.class);
Call<Result> call = request.login("admin","123456","18289454846","123456");

步骤5:调用enqueue异步发送请求

call.enqueue(new Callback<Result>() {
            @Override
            public void onResponse(Call<Result> call, Response<Result> response) {
                System.out.println(response.body());
            }

            @Override
            public void onFailure(Call<Result> call, Throwable t) {
                System.out.println(t.getMessage());
            }
        });

步骤6:对响应进行处理 打印成功或者失败信息

运行结果:

Result{code='0000', data=Data{verifySuccess=true, userInfo=UserInfo{username='admin', email='w.fbckyti@rgpvhn.as', address='@address'}}}`

Demo地址https://github.com/ByteYuhb/DemoRetrofit

5.总结

  • 静下心来看完本篇文章,相信你一定会有所收获
  • 如果想了解Retrofit源码部分,请看这篇:[Android体系课学习 之 网络请求库Retrofit源码分析]()
  • Android体系课学习 之 开源框架系列

    [Android体系课学习 之 网络请求库OkHttp使用方式(附Demo)]()

    [Android体系课学习 之 网络请求库OkHttp看这一篇就够了]()

    Android体系课学习 之 网络请求库Retrofit使用方式(附Demo)

    Android体系课学习 之 网络请求库Retrofit源码分析

    [Android体系课学习 之 RxJava看这篇就够了]()

    [Android体系课学习 之 RxJava操作符详解]()

    [Android体系课学习 之 RxJava源码分析]()

相关文章
|
2月前
|
C++
基于Reactor模型的高性能网络库之地址篇
这段代码定义了一个 InetAddress 类,是 C++ 网络编程中用于封装 IPv4 地址和端口的常见做法。该类的主要作用是方便地表示和操作一个网络地址(IP + 端口)
165 58
|
2月前
|
网络协议 算法 Java
基于Reactor模型的高性能网络库之Tcpserver组件-上层调度器
TcpServer 是一个用于管理 TCP 连接的类,包含成员变量如事件循环(EventLoop)、连接池(ConnectionMap)和回调函数等。其主要功能包括监听新连接、设置线程池、启动服务器及处理连接事件。通过 Acceptor 接收新连接,并使用轮询算法将连接分配给子事件循环(subloop)进行读写操作。调用链从 start() 开始,经由线程池启动和 Acceptor 监听,最终由 TcpConnection 管理具体连接的事件处理。
62 2
|
2月前
基于Reactor模型的高性能网络库之Tcpconnection组件
TcpConnection 由 subLoop 管理 connfd,负责处理具体连接。它封装了连接套接字,通过 Channel 监听可读、可写、关闭、错误等
88 1
|
2月前
|
负载均衡 算法 安全
基于Reactor模式的高性能网络库之线程池组件设计篇
EventLoopThreadPool 是 Reactor 模式中实现“一个主线程 + 多个工作线程”的关键组件,用于高效管理多个 EventLoop 并在多核 CPU 上分担高并发 I/O 压力。通过封装 Thread 类和 EventLoopThread,实现线程创建、管理和事件循环的调度,形成线程池结构。每个 EventLoopThread 管理一个子线程与对应的 EventLoop(subloop),主线程(base loop)通过负载均衡算法将任务派发至各 subloop,从而提升系统性能与并发处理能力。
138 3
|
2月前
基于Reactor模式的高性能网络库github地址
https://github.com/zyi30/reactor-net.git
52 0
|
2月前
基于Reactor模型的高性能网络库之Poller(EpollPoller)组件
封装底层 I/O 多路复用机制(如 epoll)的抽象类 Poller,提供统一接口支持多种实现。Poller 是一个抽象基类,定义了 Channel 管理、事件收集等核心功能,并与 EventLoop 绑定。其子类 EPollPoller 实现了基于 epoll 的具体操作,包括事件等待、Channel 更新和删除等。通过工厂方法可创建默认的 Poller 实例,实现多态调用。
204 60
|
2月前
|
安全 调度
基于Reactor模型的高性能网络库之核心调度器:EventLoop组件
它负责:监听事件(如 I/O 可读写、定时器)、分发事件、执行回调、管理事件源 Channel 等。
180 57
|
2月前
基于Reactor模型的高性能网络库之时间篇
是一个用于表示时间戳(精确到微秒)**的简单封装类
135 57
|
2月前
|
缓存 索引
基于Reactor模式的高性能网络库之缓冲区Buffer组件
Buffer 类用于处理 Socket I/O 缓存,负责数据读取、写入及内存管理。通过预分配空间和索引优化,减少内存拷贝与系统调用,提高网络通信效率,适用于 Reactor 模型中的异步非阻塞 IO 处理。
106 3
|
1月前
|
机器学习/深度学习 算法 数据库
基于GoogleNet深度学习网络和GEI步态能量提取的步态识别算法matlab仿真,数据库采用CASIA库
本项目基于GoogleNet深度学习网络与GEI步态能量图提取技术,实现高精度步态识别。采用CASI库训练模型,结合Inception模块多尺度特征提取与GEI图像能量整合,提升识别稳定性与准确率,适用于智能安防、身份验证等领域。

热门文章

最新文章