鴻蒙系統的網絡請求框架—蒹葭

目錄:html

一、前言java

二、源碼android

三、混淆git

四、添加依賴編程

五、具體用法json

六、總結設計模式

1、前言

蒹葭(JianJia)是一款鴻蒙系統上的網絡請求框架,其實就是將安卓的Retrofit移植到鴻蒙系統上,我將鴻蒙版的Retrofit命名爲蒹葭(JianJia)。蒹葭不只能實現Retrofit的功能,還會提供一些Retrofit沒有的功能。Retrofit不支持動態替換域名,國內的應用通常都是有多個域名的,蒹葭支持動態替換域名。api

2、源碼

源碼
博客地址
要想讀懂源碼,須要具有如下技能。數組

  • 熟悉okhttp的常見用法 ;
  • 熟悉面向接口編程、反射、泛型、註解;
  • 熟悉構造者模式、適配器模式、工廠模式、策略模式、靜態代理、動態代理、責任鏈模式等設計模式。

3、混淆

若是項目開啓了混淆,請在proguard-rules.pro添加以下的代碼。關於混淆,能夠查看鴻蒙代碼配置混淆網絡

-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable
-dontwarn javax.annotation.**
-keepattributes Signature, InnerClasses, EnclosingMethod, Exceptions
# 蒹葭
-dontwarn poetry.jianjia.**
-keep class poetry.jianjia.** { *; }
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
-keepclassmembers,allowshrinking,allowobfuscation interface * {
    @poetry.jianjia.http.* <methods>; } # OkHttp3 -dontwarn okhttp3.logging.** -keep class okhttp3.internal.**{*;} -dontwarn okio.** # gson -keep class sun.misc.Unsafe { *; } -keep class com.google.gson.stream.** { *; } -keepattributes *Annotation* -keepclassmembers class * implements java.io.Serializable { static final long serialVersionUID; private static final java.io.ObjectStreamField[] serialPersistentFields; private void writeObject(java.io.ObjectOutputStream); private void readObject(java.io.ObjectInputStream); java.lang.Object writeReplace(); java.lang.Object readResolve(); } # 在個人示例代碼中,com.poetry.jianjia.bean這個包下面的類實現了Serialized接口, # 實現了Serialized接口的類不能被混淆,請把com.poetry.jianjia.bean這個包名替換成你本身的包名 -keep class com.poetry.jianjia.bean.**{*;} 

4、添加依賴

四、1 在項目根目錄下的build.gradle文件中添加mavenCentral()倉庫,打開項目根目錄下的build.gradle文件,在build.gradle文件的repositories閉包下面添加mavenCentral()

buildscript {
    repositories {
        // 添加maven中央倉庫
        mavenCentral()
        maven {
            url 'https://mirrors.huaweicloud.com/repository/maven/'
        }
        maven {
            url 'https://developer.huawei.com/repo/'
        }
        maven {
            url 'http://maven.aliyun.com/nexus/content/repositories/central/'
        }
        jcenter()
    }
    dependencies {
        classpath 'com.huawei.ohos:hap:2.4.2.5'
        classpath 'com.huawei.ohos:decctest:1.0.0.6'
    }
}

allprojects {
    repositories {
        // 添加maven中央倉庫
        mavenCentral()
        maven {
            url 'https://mirrors.huaweicloud.com/repository/maven/'
        }
        maven {
            url 'https://developer.huawei.com/repo/'
        }
        maven {
            url 'http://maven.aliyun.com/nexus/content/repositories/central/'
        }
        jcenter()
    }
}

四、2 打開entry目錄下的build.gradle文件中,在build.gradle文件中的dependencies閉包下添加下面的依賴

// 蒹葭的核心代碼
implementation 'io.gitee.zhongte:jianjia:1.0.0'
// 數據轉換器,數據轉換器使用gson來幫咱們解析json,不須要咱們手動解析json
implementation 'io.gitee.zhongte:converter-gson:1.0.0'
implementation "com.google.code.gson:gson:2.8.2"
// 日誌攔截器,經過日誌攔截器能夠看到請求頭、請求體、響應頭、響應體
implementation 'com.squareup.okhttp3:logging-interceptor:3.7.0'

四、3 在配置文件中添加以下的權限

ohos.permission.INTERNET

5、具體用法,用法跟retrofit同樣

蒹葭提供了一系列的註解,在進行網絡請求的時候,就須要用到這些註解。
五、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()); } }); 

五、2 BaseUrl註解
國內的應用通常都是有多個域名的,BaseUrl註解能夠對某個接口設置單獨的域名。

public interface Wan {
 
    @BaseUrl("https://api.apiopen.top")
    @GET("getJoke")
    Call<ResponseBody> getJoke(@QueryMap Map<String, String> param); } 

五、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 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); } 

五、5 QueryMap註解
QueryMap註解以map的形式添加查詢參數,被QueryMap註解修飾的參數類型必須是Map對象。

public interface Wan {
 
    @GET("wxarticle/list/405/1/json")
    Call<ResponseBody> search(@QueryMap Map<String, String> param); } 

五、6 SkipCallbackExecutor註解
在鴻蒙系統上,蒹葭默認會將服務端的響應回調到主線程,若是在方法上使用SkipCallbackExecutor註解,那就不會將服務端的結果回調到主線程。

public interface Wan {
    @SkipCallbackExecutor
    @GET("wxarticle/list/405/1/json")
    Call<ResponseBody> search(@QueryMap Map<String, String> param); } 

五、7 FormUrlEncoded註解和Field註解
FormUrlEncoded註解用於發送一個表單請求,使用該註解必須在方法的參數添加Field註解,被Field註解修飾的參數類型能夠是數組、集合、字符串等。

public interface Wan {
    @POST("user/login")
    @FormUrlEncoded
    Call<ResponseBody> login(@Field("username") String username, @Field("password") String password); } 

五、8 FormUrlEncoded註解和FieldMap註解
有時候表單的參數會比較多,若是使用Field註解,方法的參數就會比較多,此時就可使用FieldMap註解,FieldMap註解以鍵值對的形式發送一個表單請求。若是被FieldMap註解修飾的參數不是Map類型,就會拋異常。若是Map的鍵值對爲空,也會拋異常。

public interface Wan {
    @POST("user/login")
    @FormUrlEncoded
    Call<ResponseBody> login(@FieldMap Map<String, String> map); } 

五、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); } 

五、10 Url註解
Url註解用於添加接口的完整地址。在Retrofit裏面,若是接口的域名與建立retrofit對象指定的域名不相同,那就會使用Url註解來解決問題。在蒹葭裏面一樣可使用Url註解來解決問題,但蒹葭還提供了BaseUrl來解決該問題。

public interface Wan {
 
    @GET()
    Call<ResponseBody> getArticle(@Url String url); } 

五、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); } 

五、12 Header註解
Header註解是做用於參數上的註解,用於添加請求頭。

public interface Wan {
 
    @GET()
   Call<ResponseBody> foo(@Header("Accept-Language") String lang); } 

五、13 HeaderMap註解
HeaderMap註解是做用於參數上的註解,以map的形式添加請求頭,map中每一項的鍵和值都不能爲空,不然會拋異常。

public interface Wan {
 
    @GET("/search")
   Call<ResponseBody> list(@HeaderMap Map<String, String> headers); } 

五、14 添加數據轉換器
以前咱們在接口裏面定義方法的時候,方法的返回值時Call對象,泛型是ResponseBody。在這種狀況下,服務端返回給端上的數據就會在ResponseBody裏面,端上須要手動解析json,將json解析成一個實體類。
其實,咱們不必手動解析json,可讓gson幫咱們解析json。蒹葭支持添加數據轉換器,在建立對象的時候添加數據轉換器,也就是把gson添加進來。在onResponse方法裏面就能夠直接獲得實體類對象了,gson幫咱們把json解析成了一個實體對象。
首先在build.gradle文件添加數據轉換器的依賴。

// 數據轉換器,數據轉換器使用gson來幫咱們解析json,不須要咱們手動解析json
implementation 'io.gitee.zhongte:converter-gson:1.0.0'
implementation "com.google.code.gson:gson:2.8.2"

在代碼中使用數據轉換器

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()) { // json已經被解析成banner對象了 Banner banner = response.body(); } } catch (IOException e) { e.printStackTrace(); } } @Override public void onFailure(Call<Banner> call, Throwable t) { LogUtils.info("yunfei", t.getMessage()); } }); 

6、總結

本文介紹了蒹葭的用法,蒹葭的原理跟retrofit是同樣的,有興趣的同窗能夠去看下源碼。

 

做者:裴雲飛1

想了解更多內容,請訪問51CTO和華爲合做共建的鴻蒙社區:https://harmonyos.51cto.com

相關文章
相關標籤/搜索