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 })
      }
    )
相关推荐
BingoGo18 小时前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack18 小时前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo2 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack2 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack3 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo3 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack4 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理4 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
DianSan_ERP4 天前
电商API接口全链路监控:构建坚不可摧的线上运维防线
大数据·运维·网络·人工智能·git·servlet
呉師傅4 天前
火狐浏览器报错配置文件缺失如何解决#操作技巧#
运维·网络·windows·电脑