RxJava+Retrofit+OkHttp 网络框架封装(一)
- 前言
春节过后是找工作的高峰期,我也不例外想找一个比较是自己满意的工作。在面试了几家公司每家居然都问RxJava,Retrofit,OkHttp的实现原理,趁离任期间还是把这个好好总结下。就先对他们做下简单的详情。
RxJava+Retrofit+OkHttp 网络框架封装(一)
RxJava+Retrofit+OkHttp 网络框架封装(二)
首先简单详情Retrofit、OKHttp和RxJava之间的关系:
- Retrofit:Retrofit是Square公司开发的一款针对Android 网络请求的框架(底层默认是基于OkHttp 实现)。
- OkHttp:也是Square公司的一款开源的网络请求库。
- RxJava :”a library for composing asynchronous and event-based programs using observable sequences for the Java VM”(一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库)。RxJava使异步操作变得非常简单。
各自职责:Retrofit 负责 请求的数据 和 请求的结果,使用 接口的方式 呈现,OkHttp 负责请求的过程,RxJava 负责异步,各种线程之间的切换。
Retrofit 创立过程和参数的讲解
一、引入Retrofit的包,在build.gradle文件中增加如下配置:
在这里我们先理解一下Android的项目架构,便于不熟习Android项目架构的读者加以理解:
对于一个Android工程而言,有两个Gradle配置文件,一类是项目的Gradle配置,一类是工程的Gradle配置。每个项目(或者称为板块)都有属于自己Gradle配置,整个工程有一个通用的Gradle配置。
1)、项目中的Gradle配置主要管理项目的属性和依赖;
2)、工程中的Gradle配置主要用于管理一律项目的通用属性和工程的建构,如工程构建脚本(buildscript),库的下载地址(jcenter)等。工程中最基本的Gradle配置分为三部分,即 buildscript、allprojects、task clean。
1) buildscript 表示构建脚本,依赖库来源于 Jcenter,依赖于Gradle的Build Tools 工具包;
2) allprojects 表示一律项目的通用配置,依赖库的来源于 Jcenter;
3) task clean 表示清理命令(gradle clean)脚本,删除工程根目录的build文件。当开发小的工程时, 开发人员很少会修改工程的Gradle配置,而是更关注项目的Gradle配置。在Gradle中,一个重要的部分就是增加第三方的依赖(dependencies)。使用第三方库,可以避免重复创立轮子,加快开发速度,提升代码的稳固性。
compile 'com.squareup.retrofit2:retrofit:2.3.0'//导入retrofitcompile 'com.google.code.gson:gson:2.6.2'//Gson 库//下面两个是RxJava 和 RxAndroidcompile 'io.reactivex.rxjava2:rxandroid:2.0.2'compile 'io.reactivex.rxjava2:rxjava:2.x.y'compile 'com.squareup.retrofit2:converter-gson:2.3.0'//转换器,请求结果转换成Modelcompile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'//配合Rxjava 使用
二、定义数据Bean结构
public class DataChildBean{ private String source; private String unit; public String getSource() { return source; } public void setSource(String source) { this.source = source; } public String getUnit() { return unit; } public void setUnit(String unit) { this.unit = unit; }}
三、设计api接口
使用 POST,GET 请求方式时,只要要更改方法定义的标签,用 @POST ,@GET标签,参数标签用 @Field 或者者 @Body 或者者@ FieldMap
public interface MovieService {//比值标题栏列表@GET("rest/startFigure/tradingHelper")Call<DataChildBean> getMeasureQuotations(@Query("start") int start , @Query("count") int count);@FormUrlEncoded@POST("rest/measure/getLast")Call<DataChildBean> getMeasureInstruction(@Field("start") int start , @Field("count") int count);@POST("rest/options/exerviseprice") Call<BaseModel<ArrayList<String>>> getExervisePrice(@Body RequestBody body);}
网络请求方法和网络请求参数标签的讲解
- 网络请求方法
1、@HTTP
作用:替换@GET、@POST、@PUT、@DELETE、@HEAD注解的作用 及 更多功能拓展
具体使用:通过属性method、path、hasBody进行设置
public interface MovieService { /** * method:网络请求的方法(区分大小写) * path:网络请求地址路径 * hasBody:能否有请求体 */ @HTTP(method = "GET", path = "blog/{id}", hasBody = false) Call<ResponseBody> getCall(@Path("id") int id); // {id} 表示是一个变量 // Call 接受返回对象 // method 的值 retrofit 不会做解决,所以要自行保证精确}
2、@GET、@POST 这里就不详情了
标记类
1、@FormUrlEncoded
作用:表示发送form-encoded的数据
2、@Multipart
作用:表示发送form-encoded的数据(适用于 有文件 上传的场景)
public interface MovieService { /** *表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded) * <code>Field("username")</code> 表示将后面的 <code>String name</code> 中name的取值作为 username 的值 */ @POST("/form") @FormUrlEncoded Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age); /** * {@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);}
- 网络请求参数
1、@Header & @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作用于方法
2、 @Body
作用:以 Post方式 传递 自己设置数据类型 给服务器,可以传输json文件
特别注意:假如提交的是一个Map,那么作用相当于 @Field
//POST 网络请求, RequestBody来实现传输JSON文件 @POST("rest/basis/modifyCrossMonthSubtractionContract") Call<ResponseBody> modifyCrossMonthSubtractionContract(@Body RequestBody body);//具体实现AddOrEditMonth addOrEditMonth = new AddOrEditMonth();addOrEditMonth.setLeftContract(mContractOne);addOrEditMonth.setLeftName(mNameOne);addOrEditMonth.setOldLetfContract(oldLetfContract);String d = GsonUtil.toJson(addOrEditMonth);RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),GsonUtil.toJson(addOrEditMonth)); Call<ResponseBody> call2 = service.modifyCrossMonthSubtractionContract(body );
3、@Field & @FieldMap
作用:发送 Post请求 时提交请求的表单字段
具体使用:与 @FormUrlEncoded 注解配合使用
public interface MovieService { /** *表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded) * <code>Field("username")</code> 表示将后面的 <code>String name</code> 中name的取值作为 username 的值 */ @POST("/form") @FormUrlEncoded Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age); /** * Map的key作为表单的键 */ @POST("/form") @FormUrlEncoded Call<ResponseBody> testFormUrlEncoded2(@FieldMap Map<String, Object> map);}// 具体使用// @FieldCall<ResponseBody> call1 = service.testFormUrlEncoded1("Carson", 24);// @FieldMap // 实现的效果与上面相同,但要传入MapMap<String, Object> map = new HashMap<>();map.put("username", "Carson");map.put("age", 24);Call<ResponseBody> call2 = service.testFormUrlEncoded2(map);
4、@Url
作用:直接传入一个请求的 URL变量 用于URL设置
@GETCall<ResponseBody> testUrl@Url String ur);// 当有URL注解时,@GET传入的URL即可以省略// 当GET、POST...HTTP等方法中没有设置Url时,则必需使用 {@link Url}提供//用法String url = "/sso/checkregist/" + etLoginName.getText().toString();Call<ResponseBody> call2 = service.testUrl(map);
5、 @Path
作用:URL地址的缺省值
@GET("users/{user}/repos")Call<ResponseBody> testPath(@Path("user") String user );// 访问的API是:https://api.github.com/users/{user}/repos// 在发起请求时, {user} 会被替换为方法的第一个参数 user(被@Path注解作用)
6、@Part & @PartMap
作用:发送 Post请求 时提交请求的表单字段与@Field的区别:功能相同,但携带的参数类型更加丰富,包括数据流,所以适用于 有文件上传 的场景
具体使用:与 @Multipart 注解配合使用
public interface MovieService { //上传单个文件 @POST("/form") @Multipart Call<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file); //上传单个文件 @POST("/form") @Multipart Call<ResponseBody> testFileUpload2(@PartMap Map<String, RequestBody> args, @Part MultipartBody.Part file); //上传多个文件 @POST("/form") @Multipart Call<ResponseBody> testFileUpload3(@PartMap Map<String, RequestBody> args);}// 具体使用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"), "这里是模拟文件的内容");// @PartMultipartBody.Part filePart = MultipartBody.Part.createFormData("file", "test.txt", file);Call<ResponseBody> call3 = service.testFileUpload1(name, age, filePart);ResponseBodyPrinter.printResponseBody(call3);// @PartMap// 实现和上面同样的效果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);
7、@Query和@QueryMap
作用:用于 @GET 方法的查询参数(Query = Url 中 ‘?’ 后面的 key-value)
具体使用:配置时只要要在接口方法中添加一个参数就可:
@GET("/") Call<String> cate(@Query("cate") String cate); @GET("News") Call<NewsBean> getItem(@QueryMap Map<String, String> map); // 其使用方式同 @Field与@FieldMap
四、创立一个Retrofit 实例,并且完成相关的配置:
配置了接口的 URL 和一个 converter , GsonConverterFactory 是默认提供的 Gson转换器。
public static final String URL = "https://liveapp.shmet.com/mapi/";//在创立Retrofit实例时通过.baseUrl()设置Retrofit retrofit = new Retrofit.Builder() .baseUrl(URL) //设置网络请求的Url地址 .addConverterFactory(GsonConverterFactory.create()) .build();
- 网络请求的完整 Url =在创立Retrofit实例时通过.baseUrl()设置 +网络请求接口的注解设置(下面称 “path“ )
- 具体整合的规则如下:
1、path = 完整的url
Url = "http://host:port/a/path"path = "http://host:port/a/path"baseUrl = 不设置(即:接口中的Url是一个完整的网址,在Retrofit的实例中可以不设置URL)
2、path = 绝对路径
Url = "http://host:port/a/path"path = "/path"baseUrl = "http://host:port/a"
3、path = 相对路径 baseUrl = 目录形式
Url = "http://host:port/a/path"path = "path"baseUrl = "http://host:port/a/"
4、path = 相对路径 baseUrl = 文件形式
Url = "http://host:port/a/path"path = "path"baseUrl = "http://host:port/a"
建议采用第三种方式来配置,并尽量使用同一种路径形式。
五、取得api接口的代理商对象(即创立网络请求接口实例):
// 创立 网络请求接口 的实例MovieService request = retrofit.create(MovieService.class);//对 发送请求 进行封装Call<Reception> call = request.getCall();
六、发送网络请求(异步 / 同步),解决返回数据
通过response类的 body()对返回的数据进行解决
//发送网络请求(异步)call.enqueue(new Callback<Translation>() { //请求成功时回调 @Override public void onResponse(Call<Translation> call, Response<Translation> response) { //请求解决,输出结果 response.body().show(); } //请求失败时候的回调 @Override public void onFailure(Call<Translation> call, Throwable throwable) { System.out.println("连接失败"); } });// 发送网络请求(同步)Response<Reception> response = call.execute();// 对返回数据进行解决response.body().show();
- Retrofit 的详情先简单的详情这些,以后在更加详细的补充。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » RxJava+Retrofit+OkHttp 网络框架封装(一)