Retrofit从开始到放弃

概述

在学习 Retrofit2 的过程中受到了一些阻力,现 Retrofit2 学会使用了,特此写此文验证所学知识。同时也希望帮助和我一样在学习Retrofit2遇到困难的猿们。

当我在刚开始学习 Retrofit2 的时候并不知道Retrofit2是什么东西,后来逐渐了解 “它可能是一个方便我们网络请求的库 ,可以帮我们让请求网络变得更灵活、易于维护”。然后还可以和时下比较火热的RxJava进行完美融合。

先看看如何使用,如何进行一个简单的Get/Post请求

Retrofit2 入门

首先在build.gradle中添加如下代码,添加Retrofit2库

compile 'com.squareup.retrofit2:retrofit:2.1.0'
 
 
  • 1

有的教程里写要手动添加okhttp的库,其实是不需要的,因为retrofit2封装了okhttp,不信自己编译下看看: 
gradle

External libraries

添加完库,我们开始正文。

我们在项目中进行网络请求时,肯定不是一个地址吧,那么这些请求地址存放在哪呢?是在哪个类里请求就在哪个类里存放,还是统一放在一个专门存地址的类中呢? 
我在学习Android期间就是哪里有请求就放哪里,后来有人告诉我要集中存放。于是后来就建立一个AppURL.java所有地址都存放这里。 
然而Retrofit2这里也可以这么理解:专门有一个‘地方’来存储链接地址(也可以创建多个‘地方’存储)。这个‘地方’不是类而是接口,在这个接口中可以设定请求地址的一些信息。就像这样:



public interface AppURL { 
    @GET("index") 
    Call<ResponseBody> getIndex();
    ...
    ...
//  可以存储多个连接地址
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

说明: 
接口名“AppURL ”可以随意定义,根据自己喜好。 
第一行:代表get请求,请求地址为“设定的BaseURL/index” (BaseURL设定在下面介绍如何设定) 
第二行:getIndex是方法名;Call是默认返回类型,暂且不要管能干什么。

下面我们看下如何使用这些地址进行网络请求: 
1. 创建Retrofit对象,并设定BaseURL

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://www.这里是BaseURL.com/")
                .build();
 
 
  • 1
  • 2
  • 3

需要注意的是BaseURL必须以‘/’结尾

public interface AppURL { 
    @GET("index") 
    Call<ResponseBody> getIndex();
    ...
    ...
//  可以存储多个连接地址
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

说明: 
接口名“AppURL ”可以随意定义,根据自己喜好。 
第一行:代表get请求,请求地址为“设定的BaseURL/index” (BaseURL设定在下面介绍如何设定) 
第二行:getIndex是方法名;Call是默认返回类型,暂且不要管能干什么。

下面我们看下如何使用这些地址进行网络请求: 
1. 创建Retrofit对象,并设定BaseURL

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://www.这里是BaseURL.com/")
                .build();
 
 
  • 1
  • 2
  • 3

需要注意的是BaseURL必须以‘/’结尾


  1. 获取“AppURL”对象(创建请求服务)
AppURL url= retrofit.create(AppURL.class);
 
 
  • 1
  1. 用AppURL对象得到具体请求对象(获取请求服务方法 )
Call<ResponseBody> call = getIndex.getIndex();
 
 
  • 1

后期也会在这一步中进行设置链接参数、请求头等

public interface AppURL { 
    @GET("index") 
    Call<ResponseBody> getIndex();
    ...
    ...
//  可以存储多个连接地址
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

说明: 
接口名“AppURL ”可以随意定义,根据自己喜好。 
第一行:代表get请求,请求地址为“设定的BaseURL/index” (BaseURL设定在下面介绍如何设定) 
第二行:getIndex是方法名;Call是默认返回类型,暂且不要管能干什么。

下面我们看下如何使用这些地址进行网络请求: 
1. 创建Retrofit对象,并设定BaseURL

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://www.这里是BaseURL.com/")
                .build();
 
 
  • 1
  • 2
  • 3

需要注意的是BaseURL必须以‘/’结尾


  1. 开始(异步)请求
call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                Log.e("tag", response.body().toString());//获得数据
            }
            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Log.e("tag", t.getMessage());//请求失败
            }
        });
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

好了,现在一个简单的网络请求就写完了。不是很难吧(当时我可是觉得挺难 ^_^)

单单会这些是远远不够的,那么我们如何来满足项目中各种各样的需求呢?请继续看

public interface AppURL { 
    @GET("index") 
    Call<ResponseBody> getIndex();
    ...
    ...
//  可以存储多个连接地址
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

说明: 
接口名“AppURL ”可以随意定义,根据自己喜好。 
第一行:代表get请求,请求地址为“设定的BaseURL/index” (BaseURL设定在下面介绍如何设定) 
第二行:getIndex是方法名;Call是默认返回类型,暂且不要管能干什么。

下面我们看下如何使用这些地址进行网络请求: 
1. 创建Retrofit对象,并设定BaseURL

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://www.这里是BaseURL.com/")
                .build();
 
 
  • 1
  • 2
  • 3

需要注意的是BaseURL必须以‘/’结尾


Retrofit2 进阶

自动解析

其实在Retrofit2中,我们不用自己来解析数据,Retrofit2可以帮我们自动解析,怎么做呢?请看: 
0. 添加 
在Retrofit2中是用Gson解析的,所以我们要在build.gradle中添加。

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

有写教程说还有添加gosn库,经过测试是不需要的,converter-gson中已经封装了gson库。 
需要注意的是converter-gson和retrofit版本号应为一致,在这里我都用2.1.0 
1. 创建Bean 
创建一个JavaBean,用于解析服务器返回数据。就和我们平常自己解析创建的Bean一样,推荐用As的插件JsonFormat,挺方便的。 
我们创建一个Bean起名为MBean.java(随便起的) 
2. 为retrofit添加addConverterFactory 
添加后的代码如下:

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://www.这里是BaseURL.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
 
 
  • 1
  • 2
  • 3
  • 4
  1. 修改泛型
//在AppURL 接口中修改:
@GET("index")
    Call<MBean> getIndex();
 Call<MBean> call = url.getIndex();
//调用服务请求时的修改
        call.enqueue(new Callback<MBean>() {
            @Override
            public void onResponse(Call<MBean> call, Response<MBean> response) {
                Log.e("tag", response.body().toString());//解析好的数据
            }

            @Override
            public void onFailure(Call<MBean> call, Throwable t) {
                Log.e("tag", t.getMessage());
            }
        });
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

这样输出的就直接是用Gson解析好的MBean数据了。

retrofit不仅仅只支持gson,还支持其他许多json解析库。 如: 
Jackson、Moshi、Protobuf、Wire、Simple XML、Scalars (primitives, boxed, and String) 具体请看官网

固定地址/路径替换

说到固定地址了,那么固定地址长什么样呢?

http://www.BaseURL.com/index
http://www.BaseURL.com/user
http://www.BaseURL.com/login
http://www.BaseURL.com/register/qq
http://www.BaseURL.com/register/wechat
 
 
  • 1
  • 2
  • 3
  • 4
  • 5

那么应该如何请求呢?除了上面例子中的写法还可以这样写:

    @请求类型("{name}" Call<返回类型> 方法名(@path("name") String name);
如:

  @GET("{name}")
    Call<MBean> get(@Path("name") String urlName);

//如果想访问登录的链接,在使用时就直接url.get("login");就可以。这样请求的地址就是http://www.BaseURL.com/login 是不是很方便
//注意@Path和{}中的参数名要一致
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

@Path的应该作用暂且理解为 为上面的GET请求传值

带参地址

带参地址长这样子:

www.BaseURL.com/login?page=1
www.BaseURL.com/movieTop?start=1&count=5
www.BaseURL.com/login?username=testuser&password=123456
 
 
  • 1
  • 2
  • 3

上个用的是@Path,这回用的是@Query其实和@Path一样 
直接看例子:

@GET("movieTop")
    Call<MBean> get(@Query("start") int start, @Query("count") int count);
//假设想查询电影排行榜的第1-5名,则使用时候是这样:
Call<MBean> call = url.get(1, 5);
//请求的地址是这样:www.BaseURL.com/movieTop?start=1&count=5
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
Post带Body请求

使用@Body来声明即可,如下:

 @POST("/aaa")
 Call<MBean> send( @Body UserInfo body);
//使用
Call<MBean> call=url.send();

这里的UserInfo就是要发送的实体,Retrofit2 会自动转成Gson  
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

学到这里,一般的网络请求都可以了进行,可以应付一阵子了。 
还有一些要求较高的请求,请看下节。

public interface AppURL { 
    @GET("index") 
    Call<ResponseBody> getIndex();
    ...
    ...
//  可以存储多个连接地址
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

说明: 
接口名“AppURL ”可以随意定义,根据自己喜好。 
第一行:代表get请求,请求地址为“设定的BaseURL/index” (BaseURL设定在下面介绍如何设定) 
第二行:getIndex是方法名;Call是默认返回类型,暂且不要管能干什么。

下面我们看下如何使用这些地址进行网络请求: 
1. 创建Retrofit对象,并设定BaseURL

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://www.这里是BaseURL.com/")
                .build();
 
 
  • 1
  • 2
  • 3

需要注意的是BaseURL必须以‘/’结尾


Retrofit2 大成

如果看到这里,相信对Retrofit2的基本请求会用了,那么这节就说一说其他的网络请求。

表单(FormUrlEncoded)

我们可以使用@FormUrlEncoded注解来发送表单数据。使用 @Field注解和参数来指定每个表单项的Key,value为参数的值。

@FormUrlEncoded
@POST("user/login")
Call<User> updateUser(@Field("username") String name, @Field("password") String pass);
 
 
  • 1
  • 2
  • 3
单文件上传(Multipart)
 @Multipart
    @POST("register")
    Call<User> registerUser(
      @Part MultipartBody.Part headPhoto, 
      @Part("username") RequestBody userName, 
      @Part("password") RequestBody passWord
  );
//使用
MediaType textType = MediaType.parse("text/plain");
RequestBody name = RequestBody.create(textType, "二傻子");
RequestBody pass = RequestBody.create(textType, "123456");

RequestBody photoRequestBody = RequestBody.create(MediaType.parse("image/png"), 文件对象);
MultipartBody.Part photo = MultipartBody.Part.createFormData("上传的key", "文件名.png", photoRequestBody);

Call<User> call = url.registerUser(photo,name, pass);
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

@Part 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型;

动手测试:username的RequestBody 换成String是否可以

多文件上传
@Multipart
@POST("register")
Call<User> registerUser(@PartMap Map<String, RequestBody> params,  @Part("password") RequestBody password);
//使用
RequestBody photo = RequestBody.create(MediaType.parse("image/png"), 文件对象2);
RequestBody photo = RequestBody.create(MediaType.parse("image/png"), 文件对象2);
Map<String,RequestBody> photos = new HashMap<>();
photos.put("对应的key1"; filename=\"文件名1.png", photo1);
photos.put("对应的key2"; filename=\"文件名2.png", photo2);
photos.put("username",  RequestBody.create(null, "二傻子"));

Call<User> call = userBiz.registerUser(photos, RequestBody.create(null, "123456"));
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

也可以都塞Map里上传,也可以只在Map中上传文件,随你喽~ 
文章结尾有参考链接。不一样的上传方式。

请求头
  1. 固定请求头
     @GET("地址")
     @Headers("Accept-Encoding: application/json")
     Call<返回类型> 方法名();
    // 请求结果:
    // GET 地址 HTTP/1.1
    // Accept-Encoding: application/json
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  1. 动态请求头
     @GET("地址")
     Call<返回类型> 方法名(@Header("Location") String location);
    //使用
    url.方法名("参数");
    // 请求结果:
    // GET 地址 HTTP/1.1
    // Location: 参数
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  1. 固定+动态
     @GET("地址")
     @Headers("Accept-Encoding: application/json")
     Call<返回类型> 方法名(@Header("Location") String location);
    //使用
    url.方法名("参数");
    // 请求结果:
    // GET 地址 HTTP/1.1
    // Accept-Encoding: application/json
    // Location: 参数
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
其他
  1. 注意XXXMap的使用, 比如@PathMap,@FieldMap等,具体怎么使用,可以自己研究,研究不出来的可以参考结尾处的文章。

  2. 下载文件得说说,在Retrofit2中下载文件是默认存储到缓存中,也就是说不能进行大的文件下载,如果要下载大文件要用 @streaming 。但话说回来了,下载文件我们可以不用Retrofit2啊,直接用okhttp不就得啦

  3. 我们是可以添加 okhttpclient 到retrofit中去,这样可以来统一的log管理,给每个请求添加统一的header等,那么我们没有添加为什么没有报错呢? 因为在build()方法中会判断是否为空,如果我们没有添加okhttpclient 则就是空了,那么retrofit会自动给我们添加了一个new OkHttpClient();

  4. execute是同步执行 需要在子线程中执行、enqueue是异步执行。
  5. 看下我这几个图,整理一下思路吧

HTTP请求方法

以上表格中的除HTTP以外都对应了HTTP标准中的请求方法,而HTTP注解则可以代替以上方法中的任意一个注解,有3个属性:method、path、hasBody, 这里是用HTTP注解实现的例子

public interface BlogService {
    /**
     * method 表示请的方法,不区分大小写
     * path表示路径
     * hasBody表示是否有请求体
     */
    @HTTP(method = "get", path = "blog/{id}", hasBody = false)
    Call<ResponseBody> getFirstBlog(@Path("id") int id);
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

标记类

参数类

注1:{占位符}和PATH尽量只用在URL的path部分,url中的参数使用Query和QueryMap 代替,保证接口定义的简洁 
注2:Query、Field和Part这三者都支持数组和实现了Iterable接口的类型,如List,Set等,方便向后台传递数组。

    Call<ResponseBody> foo(@Query("ids[]") List<Integer> ids);
    //结果:ids[]=0&ids[]=1&ids[]=2
 
 
  • 1
  • 2

Retrofit2 独断万古

首先说下如何和当前火热的RxJava进行配合使用。

  1. 引入RxJava支持 (版本号要一致)
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
 
 
  • 1
  1. 写接口
@GET(" ^_^ ")
    Observable<MBean> get();
 
 
  • 1
  • 2
  1. 通过RxJavaCallAdapterFactory为Retrofit添加RxJava支持
Retrofit retrofit = new Retrofit.Builder()
      .baseUrl("http://www.BaseURL.com/")
      .addConverterFactory(GsonConverterFactory.create())//自动通过Gson转josn,上面有提到
      .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//添加RxJava支持
      .build();
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  1. 使用
url.get()
        .subscribeOn(Schedulers.io())
        .subscribe(new Subscriber<MBean>() {
            @Override
            public void onCompleted() {
            }
            @Override
            public void onError(Throwable e) {
            }
            @Override
            public void onNext(MBean mBean) {
            }
        });
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

根据需要添加RxAndroid,这个版本号没有要求。

剩下的内容讲的主要是进行自定义 Converter 和 自定义CallAdapter。还有就是源码的解析。 
这里可以参考结尾处的链接,不献丑了。


public interface AppURL { 
    @GET("index") 
    Call<ResponseBody> getIndex();
    ...
    ...
//  可以存储多个连接地址
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

说明: 
接口名“AppURL ”可以随意定义,根据自己喜好。 
第一行:代表get请求,请求地址为“设定的BaseURL/index” (BaseURL设定在下面介绍如何设定) 
第二行:getIndex是方法名;Call是默认返回类型,暂且不要管能干什么。

下面我们看下如何使用这些地址进行网络请求: 
1. 创建Retrofit对象,并设定BaseURL

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://www.这里是BaseURL.com/")
                .build();
  
  
  • 1
  • 2
  • 3

需要注意的是BaseURL必须以‘/’结尾

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,你需要先从数据库中查询出参数。可以使用JDBC连接数据库,使用SQL语句从数据库中查询出需要的参数。例如: ``` String query = "SELECT parameter1, parameter2 FROM my_table WHERE id = ?"; PreparedStatement pstmt = connection.prepareStatement(query); pstmt.setInt(1, id); // 假设需要查询的是id为1的记录 ResultSet rs = pstmt.executeQuery(); if (rs.next()) { String parameter1 = rs.getString("parameter1"); int parameter2 = rs.getInt("parameter2"); // 这里可以将查询出来的参数上传到接口 } ``` 接下来,你可以使用Retrofit来上传参数到接口。假设接口是一个POST请求,上传的参数是JSON格式的数据。可以使用Retrofit的注解来定义接口方法和参数。例如: ``` public interface MyApi { @POST("my_endpoint") Call<MyResponse> uploadData(@Body MyData data); } public class MyData { private String parameter1; private int parameter2; // getter和setter } // 创建Retrofit实例 Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://my.api.com/") .build(); // 创建API代理 MyApi api = retrofit.create(MyApi.class); // 构造请求参数 MyData data = new MyData(); data.setParameter1(parameter1); data.setParameter2(parameter2); // 发送请求 Call<MyResponse> call = api.uploadData(data); Response<MyResponse> response = call.execute(); ``` 这样,就可以从数据库查询参数后上传到接口了。注意,这里只是示例代码,具体实现需要根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值