Harmony os Next——Retrofit网络库的使用和封装

这里写目录标题

Harmony os Next------Retrofit网络库的使用和封装

描述

Retrofit作为Android平台最为常用的一个第三方网络库,搭配Kotlin的协程,使用极为便捷。通过Harmony的工作人员的努力,制作出的Retrofit For Harmony Library依旧十分强大。

通过在oh-package.json5文件中添加如下依赖即可完成装配,具体版本可以查看retrofit api

"@ohos/retrofit": "2.0.1-rc.0"

同时也可以通过添加httpclient为其添加拦截器等

"@ohos/httpclient": "2.0.0-rc.9",

Retrofit的使用

BaseService

需要创建一个类继承BaseService。同时可以在类名上方加一个@BasePath("/")注解。

意味在BaseUrl后面补全一个/。因为在后面通过ServiceBuilder创建AppService实例时,需要指定BaseUrl,例如BaseUrlhttps://api.xxxx.com,在类上面添加注解@BasePath("/"),便会自动在BaseUrl后面加一个/,后面的具体接口就不需要加/,例如有一个获取天气的子接口api/weather,最终拼凑的就是https://api.xxxx.com/api/weather

c 复制代码
@BasePath("/")
class AppService extends BaseService{
}

部分功能使用

GET

其中NetworkConstants.GET_WEATHER就是上述举例的api/weather,在其前面使用GET注解进行包裹,然后可以通过@Query传递参数。最后返回的数据是通过异步的方式返回。Promise<Response<...>>为固定返回参数,BaseModel<WeatherModel>为api接口返回的JSON数据格式,可根据项目自行定义

c 复制代码
@BasePath("/")
class AppService extends BaseService{
 @GET(NetworkConstants.GET_WEATHER)
  async getWeather(
    @Query("cityId") cityId: string
  ): Promise<Response<BaseModel<WeatherModel>>> { return {} as Response<BaseModel<WeatherModel>> }
}

POST

GET使用一致,通过POST注解进行包裹,同样可以使用@Field进行参数传递,其中 @FormUrlEncoded注解是给此方法添加如下参数头

'content-type': 'application/x-www-form-urlencoded;charset=utf-8'

c 复制代码
@BasePath("/")
class AppService extends BaseService{
  @FormUrlEncoded
  @POST(NetworkConstants.TEST_API)
  async postTestApi(
    @Field("testId")testId : string
  ): Promise<Response<BaseModel<TestModel>>> { return {} as Response<BaseModel<TestModel>> }
}

创建拦截器

以打印日子拦截器为例,可以将每一个API请求的方法、参数、URL、返回结果等进行打印输出,便于测试。具体如下

c 复制代码
class LoggingInterceptor implements Interceptor{
  async intercept(chain: Chain): Promise<Response> {
    try {
      let request = chain.requestI()
      let requestBody: RequestBody = request.body
      let url = request.url as HttpUrl
      const connectResponse = await chain.proceedI(chain.requestI())
      let startMessage = `-->${request.method} ${url.url} ${connectResponse.protocol ?? ''}`
      let contentType: string = requestBody.content
      let endMessage = `--> END ${request.method}`
      Logger.info(`Headers:${JSON.stringify(request.headers)}`)
      Logger.info(startMessage)
      Logger.info(contentType)
      Logger.info(endMessage)
      return connectResponse
    } catch (error) {
      return new Promise<Response>((resolve, reject) => {
        let request = chain.requestI()
        let response = chain.proceedI(request)
        response.then((data) => {
          resolve(data)
        }).catch((err: Error) => {
          reject(err)
        });
      })
    }
  }
}

创建实例

通过addInterceptor便可以添加上述我们创建的日志打印拦截器

通过setEndpoint可以设置BASEURL

通过在build函数里面指定需要创建的BaseService子类

c 复制代码
let client: HttpClient = new  HttpClient.Builder()
  .setConnectTimeout(5, TimeUnit.SECONDS)
  .setReadTimeout(5, TimeUnit.SECONDS)
  .addInterceptor(loggingInterceptor)
  .build()

export const appService = new ServiceBuilder()
  .setEndpoint(NetworkConstants.BASEURL)
  .setClient(client)
  .build(AppService)

全局封装

通过创建一个全局范型方法baseApiRequest,将api请求的异常进行集中处理,只对其成功返回的结果和错误进行返回,可以避免重复异常处理

c 复制代码
export function baseApiRequest<T>(
    apiCall: Promise<Response<T>>,
    onSuccess: (result: T) => void,
    onFailed: (error: ResourceStr) => void
) {
  apiCall.then((result: Response<T>) => {
    if (result.isSuccessful() && result.code() == HttpStatusCode.SUCCESS) {
      onSuccess(result.result)
    } else {
      onFailed(result.message())
    }
  }).catch((error: Error) => {
    if (error as IOException) {
      //网络错误
      onFailed($r('app.string.HH_Public_DisconnectNetwork'))
    }else {
      onFailed(error.message)
    }
  })
}

具体使用如下所示,就此我们就可以将一个网络请求接口简化到下面方法一样

c 复制代码
baseApiRequest(
      appService.getWeather(citeId),
      (result) => {
        if (result.code === HttpStatusCode.SUCCESS) {
         //successful
        } else {
        //failed-error code
          promptAction.showToast({ message: result.message })
        }
      },
      (error) => {
      //failed
        Logger.info(`${error}`)
        promptAction.showToast({ message: error })
      }
    )
相关推荐
你怎么睡得着的!1 小时前
【护网行动-红蓝攻防】第一章-红蓝对抗基础 认识红蓝紫
网络·安全·web安全·网络安全
anddddoooo6 小时前
域内证书维权
服务器·网络·网络协议·安全·网络安全·https·ssl
Long._.L6 小时前
OpenSSL实验
网络·密码学
Dyan_csdn6 小时前
【Python项目】基于Python的Web漏洞挖掘系统
网络·python·安全·web安全
okok__TXF7 小时前
Rpc导读
网络·网络协议·rpc
&向上8 小时前
RK3588配置成为路由器
网络·智能路由器·rk3588
猫猫的小茶馆8 小时前
【网络编程】UDP协议
linux·服务器·网络·网络协议·ubuntu·udp
十月ooOO9 小时前
小米AX3000T 路由器如何开启 SSH 安装 OpenWRT 系统,不需要降级 v1.0.91 (2025)
网络·ssh·路由器·openwrt
SKYDROID云卓小助手9 小时前
无人设备遥控器之如何分享数传篇
网络·人工智能·算法·计算机视觉·电脑