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 })
      }
    )
相关推荐
Sirius Wu6 分钟前
OpenClaw(UpClaw)三层Tool全链路治理深度详解
网络·人工智能·架构·aigc
源图客19 分钟前
云途物流API开发-鉴权认证(Java)
java·网络·python
huashengzsj1 小时前
Shopify个人建站如何搭建独立站:从零开始的完整指南
前端·网络·人工智能
木木子221 小时前
[特殊字符] 音乐播放器——状态驱动的多媒体控制
android·开发语言·华为·php·harmonyos
酷酷的身影2 小时前
Drivers/LedManager.cs
开发语言·php
云飞云共享云桌面2 小时前
单机建模卡顿运维繁琐!中小型机械制造厂云飞云 3D 云桌面落地
运维·服务器·网络·3d·自动化·电脑·负载均衡
mounter6252 小时前
BPF 的进化史:从网络过滤器到 AI 时代的 Linux 核心引擎
linux·网络·人工智能·ebpf·linux kernel·kernel
CryptoPP2 小时前
BSE股票K线数据接入实战:从接口调用到前端图表展示
大数据·前端·网络·人工智能·websocket·网络协议
可靠的仙人掌2 小时前
SAC(Soft Actor-Critic)算法底座
开发语言·算法·php
液态不合群3 小时前
卡死在生产流程?AI破解制造业数字化落地顽疾
网络·人工智能·低代码·重构