文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

鸿蒙系统的网络请求框架—蒹葭

2024-12-03 05:51

关注

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

一、前言

蒹葭(JianJia)是一款鸿蒙系统上的网络请求框架,其实就是将安卓的Retrofit移植到鸿蒙系统上,我将鸿蒙版的Retrofit命名为蒹葭(JianJia)。蒹葭不仅能实现Retrofit的功能,还会提供一些Retrofit没有的功能。Retrofit不支持动态替换域名,国内的应用一般都是有多个域名的,蒹葭支持动态替换域名。

二、源码

源码

博客地址

要想读懂源码,需要具备以下技能。

三、混淆

如果项目开启了混淆,请在proguard-rules.pro添加如下的代码。关于混淆,可以查看鸿蒙代码配置混淆

  1. -renamesourcefileattribute SourceFile 
  2. -keepattributes SourceFile,LineNumberTable 
  3. -dontwarn javax.annotation.** 
  4. -keepattributes Signature, InnerClasses, EnclosingMethod, Exceptions 
  5. # 蒹葭 
  6. -dontwarn poetry.jianjia.** 
  7. -keep class poetry.jianjia.** { *; } 
  8. -keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations 
  9. -keepclassmembers,allowshrinking,allowobfuscation interface * { 
  10.     @poetry.jianjia.http.* 
  11.  
  12. # OkHttp3 
  13. -dontwarn okhttp3.logging.** 
  14. -keep class okhttp3.internal.**{*;} 
  15. -dontwarn okio.** 
  16.  
  17. # gson 
  18. -keep class sun.misc.Unsafe { *; } 
  19. -keep class com.google.gson.stream.** { *; } 
  20. -keepattributes *Annotation* 
  21. -keepclassmembers class * implements java.io.Serializable { 
  22.     static final long serialVersionUID; 
  23.     private static final java.io.ObjectStreamField[] serialPersistentFields; 
  24.     private void writeObject(java.io.ObjectOutputStream); 
  25.     private void readObject(java.io.ObjectInputStream); 
  26.     java.lang.Object writeReplace(); 
  27.     java.lang.Object readResolve(); 
  28. # 在我的示例代码中,com.poetry.jianjia.bean这个包下面的类实现了Serialized接口, 
  29. # 实现了Serialized接口的类不能被混淆,请把com.poetry.jianjia.bean这个包名替换成你自己的包名 
  30. -keep class com.poetry.jianjia.bean.**{*;} 

 四、添加依赖

1 在项目根目录下的build.gradle文件中添加mavenCentral()仓库,打开项目根目录下的build.gradle文件,在build.gradle文件的repositories闭包下面添加mavenCentral()

  1. buildscript { 
  2.     repositories { 
  3.         // 添加maven中央仓库 
  4.         mavenCentral() 
  5.         maven { 
  6.             url 'https://mirrors.huaweicloud.com/repository/maven/' 
  7.         } 
  8.         maven { 
  9.             url 'https://developer.huawei.com/repo/' 
  10.         } 
  11.         maven { 
  12.             url 'http://maven.aliyun.com/nexus/content/repositories/central/' 
  13.         } 
  14.         jcenter() 
  15.     } 
  16.     dependencies { 
  17.         classpath 'com.huawei.ohos:hap:2.4.2.5' 
  18.         classpath 'com.huawei.ohos:decctest:1.0.0.6' 
  19.     } 
  20.  
  21. allprojects { 
  22.     repositories { 
  23.         // 添加maven中央仓库 
  24.         mavenCentral() 
  25.         maven { 
  26.             url 'https://mirrors.huaweicloud.com/repository/maven/' 
  27.         } 
  28.         maven { 
  29.             url 'https://developer.huawei.com/repo/' 
  30.         } 
  31.         maven { 
  32.             url 'http://maven.aliyun.com/nexus/content/repositories/central/' 
  33.         } 
  34.         jcenter() 
  35.     } 

 4、2 打开entry目录下的build.gradle文件中,在build.gradle文件中的dependencies闭包下添加下面的依赖

  1. // 蒹葭的核心代码 
  2. implementation 'io.gitee.zhongte:jianjia:1.0.0' 
  3. // 数据转换器,数据转换器使用gson来帮我们解析json,不需要我们手动解析json 
  4. implementation 'io.gitee.zhongte:converter-gson:1.0.0' 
  5. implementation "com.google.code.gson:gson:2.8.2" 
  6. // 日志拦截器,通过日志拦截器可以看到请求头、请求体、响应头、响应体 
  7. implementation 'com.squareup.okhttp3:logging-interceptor:3.7.0' 

 4、3 在配置文件中添加如下的权限

  1. ohos.permission.INTERNET 

五、具体用法,用法跟retrofit一样

蒹葭提供了一系列的注解,在进行网络请求的时候,就需要用到这些注解。

1 GET注解

创建接口,在方法里面使用GET注解,GET注解用于标识这是一个GET请求,方法的返回值是Call对象,泛型是ResponseBody,其实泛型也可以是具体的实体对象,这个后面再说。蒹葭如何完成网络请求?使用构造者模式创建jianjia对象,baseUrl就是域名,在创建jianjia对象的时候就必须指定域名。调用create方法来生成接口的实例,调用wan.getBanner().enqueue来执行网络请求,请求成功就会回调onResponse方法,请求失败就会回调onFailure方法。

  1. public interface Wan { 
  2.   
  3.     @GET("banner/json"
  4.     Call getBanner(); 
  5.   
  6. JianJia jianJia = new JianJia.Builder() 
  7.         .baseUrl("https://www.wanandroid.com"
  8.         .build(); 
  9.   
  10. Wan wan = jianJia.create(Wan.class); 
  11. wan.getBanner().enqueue(new Callback() { 
  12.     @Override 
  13.     public void onResponse(Call call, Response response) { 
  14.         try { 
  15.             String json = response.body().string(); 
  16.         } catch (IOException e) { 
  17.             e.printStackTrace(); 
  18.         } 
  19.     } 
  20.   
  21.     @Override 
  22.     public void onFailure(Call call, Throwable t) { 
  23.         LogUtils.info("yunfei", t.getMessage()); 
  24.     } 
  25. }); 

 5、2 BaseUrl注解

国内的应用一般都是有多个域名的,BaseUrl注解可以对某个接口设置单独的域名。

  1. public interface Wan { 
  2.   
  3.     @BaseUrl("https://api.apiopen.top"
  4.     @GET("getJoke"
  5.     Call getJoke(@QueryMap Map param); 
  6.       

 5、3 Path注解

Path注解在路径中替换指定的参数值,定义下面的方法。可以看到我们定义了一个getArticle方法,方法接收一个page参数,并且我们的@GET注解中使用{page}声明了访问路径,这里你可以把{page}当做占位符,而实际运行中会通过@Path("page")所标注的参数进行替换。

  1. public interface Wan { 
  2.   
  3.     @GET("article/list/{page}/json"
  4.     Call getArticle(@Path("page"int page); 
  5.   

 5、4 Query注解

Query注解用于给get请求添加请求参数,被Query注解修饰的参数类型可以是数组、集合、字符串等。

  1. public interface Wan { 
  2.   
  3.     @GET("wxarticle/list/405/1/json"
  4.     Call search(@Query("k") String k); 
  5.   
  6.     @GET("wxarticle/list/405/1/json"
  7.     Call search(@Query("k") String... k); 
  8.   
  9.     @GET("wxarticle/list/405/1/json"
  10.     Call search(@Query("k") List k); 
  11.   

 5、5 QueryMap注解

QueryMap注解以map的形式添加查询参数,被QueryMap注解修饰的参数类型必须是Map对象。

  1. public interface Wan { 
  2.   
  3.     @GET("wxarticle/list/405/1/json"
  4.     Call search(@QueryMap Map param); 
  5.       

 5、6 SkipCallbackExecutor注解

在鸿蒙系统上,蒹葭默认会将服务端的响应回调到主线程,如果在方法上使用SkipCallbackExecutor注解,那就不会将服务端的结果回调到主线程。

  1. public interface Wan { 
  2.     @SkipCallbackExecutor 
  3.     @GET("wxarticle/list/405/1/json"
  4.     Call search(@QueryMap Map param); 
  5.       

 5、7 FormUrlEncoded注解和Field注解

FormUrlEncoded注解用于发送一个表单请求,使用该注解必须在方法的参数添加Field注解,被Field注解修饰的参数类型可以是数组、集合、字符串等。

  1. public interface Wan { 
  2.     @POST("user/login"
  3.     @FormUrlEncoded 
  4.     Call login(@Field("username") String username, @Field("password") String password); 
  5.       

 5、8 FormUrlEncoded注解和FieldMap注解

有时候表单的参数会比较多,如果使用Field注解,方法的参数就会比较多,此时就可以使用FieldMap注解,FieldMap注解以键值对的形式发送一个表单请求。如果被FieldMap注解修饰的参数不是Map类型,就会抛异常。如果Map的键值对为空,也会抛异常。

  1. public interface Wan { 
  2.     @POST("user/login"
  3.     @FormUrlEncoded 
  4.     Call login(@FieldMap Map map); 
  5.       

 5、9 Body注解

服务端会要求端上把json字符串作为请求体发给服务端。此时就可以使用Body注解定义的参数可以直接传入一个实体类,内部会把该实体序列化并将序列化后的结果直接作为请求体发送出去。

如果被Body注解修饰的参数的类型是RequestBody对象,那调用者可以不添加数据转换器,内部会使用默认的数据转换器。

如果被Body注解修饰的参数的类型不是RequestBody对象,是一个具体的实体类,那调用者需要自定义一个类,并且继承Converter.Factory。

  1. public interface Wan { 
  2.   
  3.      
  4.     @POST("user/register"
  5.     Call register(@Body RequestBody body); 
  6.   
  7.      
  8.     @POST("user/register"
  9.     Call register(@Body User user); 

 5、10 Url注解

Url注解用于添加接口的完整地址。在Retrofit里面,如果接口的域名与创建retrofit对象指定的域名不相同,那就会使用Url注解来解决问题。在蒹葭里面同样可以使用Url注解来解决问题,但蒹葭还提供了BaseUrl来解决该问题。

  1. public interface Wan { 
  2.   
  3.     @GET() 
  4.     Call getArticle(@Url String url); 
  5.       

 5、11 Headers注解

Headers注解是作用于方法上的注解,用于添加一个或多个请求头。

  1. public interface Wan { 
  2.   
  3.     @Headers("Cache-Control: max-age=640000"
  4.     @GET("/"
  5.     Call getArticle(@Url String url); 
  6.       
  7.     @Headers({ 
  8.      "X-Foo: Bar"
  9.      "X-Ping: Pong" 
  10.    }) 
  11.     @GET("/"
  12.     Call getArticle(@Url String url); 
  13.       

 5、12 Header注解

Header注解是作用于参数上的注解,用于添加请求头。

  1. public interface Wan { 
  2.   
  3.     @GET() 
  4.    Call foo(@Header("Accept-Language") String lang); 
  5.       

 5、13 HeaderMap注解

HeaderMap注解是作用于参数上的注解,以map的形式添加请求头,map中每一项的键和值都不能为空,否则会抛异常。

  1. public interface Wan { 
  2.   
  3.     @GET("/search"
  4.    Call list(@HeaderMap Map headers); 
  5.       

 5、14 添加数据转换器

之前我们在接口里面定义方法的时候,方法的返回值时Call对象,泛型是ResponseBody。在这种情况下,服务端返回给端上的数据就会在ResponseBody里面,端上需要手动解析json,将json解析成一个实体类。

其实,我们没必要手动解析json,可以让gson帮我们解析json。蒹葭支持添加数据转换器,在创建对象的时候添加数据转换器,也就是把gson添加进来。在onResponse方法里面就可以直接得到实体类对象了,gson帮我们把json解析成了一个实体对象。

首先在build.gradle文件添加数据转换器的依赖。

  1. // 数据转换器,数据转换器使用gson来帮我们解析json,不需要我们手动解析json 
  2. implementation 'io.gitee.zhongte:converter-gson:1.0.0' 
  3. implementation "com.google.code.gson:gson:2.8.2" 

 在代码中使用数据转换器

  1. public interface Wan { 
  2.   
  3.     @GET("banner/json"
  4.     Call getBanner(); 
  5.   
  6. JianJia jianJia = new JianJia.Builder() 
  7.         .baseUrl("https://www.wanandroid.com"
  8.         .addConverterFactory(GsonConverterFactory.create()) 
  9.         .build(); 
  10.   
  11. Wan wan = jianJia.create(Wan.class); 
  12. wan.getBanner().enqueue(new Callback() { 
  13.     @Override 
  14.     public void onResponse(Call call, Response response) { 
  15.         try { 
  16.             if (response.isSuccessful()) { 
  17.                 // json已经被解析成banner对象了 
  18.                 Banner banner = response.body(); 
  19.             } 
  20.         } catch (IOException e) { 
  21.             e.printStackTrace(); 
  22.         } 
  23.     } 
  24.   
  25.     @Override 
  26.     public void onFailure(Call call, Throwable t) { 
  27.         LogUtils.info("yunfei", t.getMessage()); 
  28.     } 
  29. }); 

 六、总结

本文介绍了蒹葭的用法,蒹葭的原理跟retrofit是一样的,有兴趣的同学可以去看下源码。

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

来源:鸿蒙社区内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯