一、亮点介绍:
自从鸿蒙手机版公布以来,我就始终在做移植的工作,将安卓代码移植到鸿蒙零碎上。Retrofit 是安卓零碎上一款优良的网络申请框架,鸿蒙零碎并没有相似的网络申请框架。于是,我决定实现一套鸿蒙版的 Retrofit。
蒹葭 (JianJia) 是一款鸿蒙零碎上的网络申请框架,其实就是将安卓的 Retrofit 移植到鸿蒙零碎上,我将鸿蒙版的 Retrofit 命名为蒹葭(JianJia)。蒹葭不仅能实现 Retrofit 的性能,还会提供一些 Retrofit 没有的性能。Retrofit 不反对动静替换域名,国内的利用个别都是有多个域名的,蒹葭反对动静替换域名。Retrofit 并不可能间接增加拦截器,只能通过 okhttp 来增加拦截器,蒹葭会反对增加拦截器。
二、Demo 编译及成果出现如下:
Demo 演示视频戳此
注:文档附件在最上面
三、源码:
https://gitee.com/zhongte/JianJia
要想读懂源码,须要具备以下技能。
相熟 okhttp 的常见用法
相熟面向接口编程、反射、泛型、注解
相熟结构者模式、适配器模式、工厂模式、策略模式、动态代理、动静代理、责任链模式等设计模式
四、用法,用法跟 Retrofit 一样
蒹葭提供了一系列的注解,在进行网络申请的时候,就须要用到这些注解。
4.1 GET 注解
创立接口,在办法外面应用 GET 注解,GET 注解用于标识这是一个 GET 申请,办法的返回值是 Call 对象,泛型是 ResponseBody,其实泛型也能够是具体的实体对象,这个前面再说。蒹葭如何实现网络申请?应用结构者模式创立 jianjia 对象,baseUrl 就是域名,在创立 jianjia 对象的时候就必须指定域名。调用 create 办法来生成接口的实例,调用 wan.getBanner().enqueue 来执行网络申请,申请胜利就会回调 onResponse 办法,申请失败就会回调 onFailure 办法
public interface Wan {@GET("banner/json")
Call<ResponseBody> getBanner();}
JianJia jianJia = new JianJia.Builder()
.baseUrl("https://www.wanandroid.com")
.build();
Wan wan = jianJia.create(Wan.class);
wan.getBanner().enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {String json = response.body().string();} catch (IOException e) {e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {LogUtils.info("yunfei", t.getMessage());
}
});
4.2 BaseUrl 注解
国内的利用个别都是有多个域名的,BaseUrl 注解能够对某个接口设置独自的域名。
public interface Wan {@BaseUrl("https://api.apiopen.top")
@GET("getJoke")
Call<ResponseBody> getJoke(@QueryMap Map<String, String> param);
}
4.3 Path 注解
Path 注解在门路中替换指定的参数值,定义上面的办法。能够看到咱们定义了一个 getArticle 办法,办法接管一个 page 参数,并且咱们的 @GET 注解中应用 {page} 申明了拜访门路,这里你能够把 {page} 当做占位符,而理论运行中会通过 @Path(“page”)所标注的参数进行替换。
public interface Wan {@GET("article/list/{page}/json")
Call<ResponseBody> getArticle(@Path("page") int page);
}
4.4 Query 注解
Query 注解用于给 get 申请增加申请参数,被 Query 注解润饰的参数类型能够是数组、汇合、字符串等
public interface Wan {@GET("wxarticle/list/405/1/json")
Call<ResponseBody> search(@Query("k") String k);
@GET("wxarticle/list/405/1/json")
Call<ResponseBody> search(@Query("k") String... k);
@GET("wxarticle/list/405/1/json")
Call<ResponseBody> search(@Query("k") List<String> k);
}
4.5 QueryMap 注解
QueryMap 注解以 map 的模式增加查问参数,被 QueryMap 注解润饰的参数类型必须是 Map 对象
public interface Wan {@GET("wxarticle/list/405/1/json")
Call<ResponseBody> search(@QueryMap Map<String, String> param);
}
4.6 SkipCallbackExecutor 注解
在鸿蒙零碎下,默认会将服务端的响应回调到主线程,如果在办法上应用 SkipCallbackExecutor 注解,那就不会将服务端的后果回调到主线程
public interface Wan {
@SkipCallbackExecutor
@GET("wxarticle/list/405/1/json")
Call<ResponseBody> search(@QueryMap Map<String, String> param);
}
4.7 FormUrlEncoded 注解和 Field 注解
FormUrlEncoded 注解用于发送一个表单申请,应用该注解必须在办法的参数增加 Field 注解,被 Field 注解润饰的参数类型能够是数组、汇合、字符串等
public interface Wan {@POST("user/login")
@FormUrlEncoded
Call<ResponseBody> login(@Field("username") String username, @Field("password") String password);
}
4.8 FormUrlEncoded 注解和 FieldMap 注解
有时候表单的参数会比拟多,如果应用 Field 注解,办法的参数就会比拟多,此时就能够应用 FieldMap 注解,FieldMap 注解以 map 的模式发送一个表单申请。如果被 FieldMap 注解润饰的参数不是 Map 类型,就会抛异样。如果 Map 的键值对为空,也会抛异样。
public interface Wan {@POST("user/login")
@FormUrlEncoded
Call<ResponseBody> login(@FieldMap Map<String, String> map);
}
4.9 Body 注解
服务端会要求端上把 json 字符串作为申请体发给服务端。此时就能够应用 Body 注解定义的参数能够间接传入一个实体类,外部会把该实体序列化并将序列化后的后果间接作为申请体发送进来。
如果被 Body 注解润饰的参数的类型是 RequestBody 对象,那调用者能够不增加数据转换器,外部会应用默认的数据转换器
如果被 Body 注解润饰的参数的类型不是 RequestBody 对象,是一个具体的实体类,那调用者须要自定义一个类,并且继承 Converter.Factory
public interface Wan {
/**
* 被 Body 注解润饰的参数的类型是 RequestBody 对象,那调用者能够不增加数据转换器,外部会应用默认的数据转换器
*
* @param body
* @return
*/
@POST("user/register")
Call<ResponseBody> register(@Body RequestBody body);
/**
* 被 Body 注解润饰的参数的类型不是 RequestBody 对象,是一个具体的实体类,那调用者须要自定义一个类,并且继承 Converter.Factory
*
* @param user
* @return
*/
@POST("user/register")
Call<ResponseBody> register(@Body User user);
}
4.10 Url 注解
Url 注解用于增加接口的残缺地址。在 Retrofit 外面,如果接口的域名与创立 retrofit 对象指定的域名不雷同,那就会应用 Url 注解来解决问题。在蒹葭外面同样能够应用 Url 注解来解决问题,但蒹葭还提供了 BaseUrl 来解决该问题。
public interface Wan {@GET()
Call<ResponseBody> getArticle(@Url String url);
}
4.11 Headers 注解
Headers 注解是作用于办法上的注解,用于增加一个或多个申请头。
public interface Wan {@Headers("Cache-Control: max-age=640000")
@GET("/")
Call<ResponseBody> getArticle(@Url String url);
@Headers({
"X-Foo: Bar",
"X-Ping: Pong"
})
@GET("/")
Call<ResponseBody> getArticle(@Url String url);
}
4.12 Header 注解
Header 注解是作用于参数上的注解,用于增加申请头
public interface Wan {@GET()
Call<ResponseBody> foo(@Header("Accept-Language") String lang);
}
4.13 HeaderMap 注解
HeaderMap 注解是作用于参数上的注解,以 map 的模式增加申请头,map 中每一项的键和值都不能为空,否则会抛异样
public interface Wan {@GET("/search")
Call<ResponseBody> list(@HeaderMap Map<String, String> headers);
}
五、增加数据转换器
之前咱们在接口外面定义方法的时候,办法的返回值时 Call 对象,泛型是 ResponseBody。在这种状况下,服务端返回给端上的数据就会在 ResponseBody 外面,端上须要手动解析 json,将 json 解析成一个实体类。
其实,咱们没必要手动解析 json,能够让 gson 帮咱们解析 json。蒹葭反对增加数据转换器,在创建对象的时候增加数据转换器,也就是把 gson 增加进来。在 onResponse 办法外面就能够间接失去实体类对象了,gson 帮咱们把 json 解析成了一个实体类。
public interface Wan {@GET("banner/json")
Call<Banner> getBanner();}
JianJia jianJia = new JianJia.Builder()
.baseUrl("https://www.wanandroid.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
Wan wan = jianJia.create(Wan.class);
wan.getBanner().enqueue(new Callback<Banner>() {
@Override
public void onResponse(Call<Banner> call, Response<Banner> response) {
try {if (response.isSuccessful()) {Banner banner = response.body();
}
} catch (IOException e) {e.printStackTrace();
}
}
@Override
public void onFailure(Call<Banner> call, Throwable t) {LogUtils.info("yunfei", t.getMessage());
}
});
六、蒹葭的后续工作
6、1 上传文件也须要应用注解,目前蒹葭还没有上传文件的注解,上传文件的注解正在开发当中。
6、2 蒹葭目前还不反对间接增加拦截器,后续会把拦截器的性能加上。
6、3 网络申请框架的二次封装,网络申请框架的二次封装该当隔离掉第三方网络框架,如果未来有更好的网络框架,或者公司要求应用公司自研的网络框架,那就能够很容易的替换掉之前的网络框架,而不须要大改特改。
6、4 因为疫情起因,我预计得在北京过年了,无奈回老家过年。所以能够趁放假的时候,给大家录视频。手把手的叫大家实现本人的网络框架,心愿可能帮忙大家了解蒹葭的实现原理。当然了,蒹葭的实现原理跟 Retrofit 的原理是截然不同的。自身蒹葭就是从 Retrofit 移植过去的,只不过蒹葭能够运行在鸿蒙零碎上。
原文链接:https://developer.huawei.com/consumer/cn/forum/topic/0204470884054220049?fid=0101303901040230869
原作者:义薄云天小关羽