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 })
      }
    )
相关推荐
网硕互联的小客服4 小时前
如何利用Elastic Stack(ELK)进行安全日志分析
linux·服务器·网络·安全
Yungoal4 小时前
php & apache构建 Web 服务器
服务器·php·apache
浩浩测试一下4 小时前
Authpf(OpenBSD)认证防火墙到ssh连接到SSH端口转发技术栈 与渗透网络安全的关联 (RED Team Technique )
网络·网络协议·tcp/ip·安全·网络安全·php
leagsoft_10035 小时前
联软NSPM自动化策略管理 助力上交所加速国产化替代提升运维效率
运维·网络·自动化
孤寂大仙v5 小时前
【计算机网络】网络层IP协议与子网划分详解:从主机通信到网络设计的底层逻辑
tcp/ip·计算机网络·php
leagsoft_10036 小时前
筑牢企业网管域安全防线,守护数字核心——联软网管域安全建设解决方案
网络·安全·网络安全
苦学编程的谢7 小时前
Java网络编程API 1
java·开发语言·网络
alien爱吃蛋挞8 小时前
【JavaEE】万字详解HTTP协议
网络·网络协议·http
vortex510 小时前
浅谈 Linux 防火墙:从原理到实践
linux·网络·php
leona_nuaa10 小时前
关于udp——mqtt运行注意事项
网络·网络协议·udp