• 作者:老汪软件技巧
  • 发表时间:2024-08-29 07:02
  • 浏览量:

第三篇:接入第三方库,使用Axios网络请求,PullToRefresh上拉刷新下拉加载

第一篇:创建一个应用,使用Tabs和导航栏结构

第二篇:使用网格Grid与列表list

第三篇:接入第三方库,使用Axios网络请求,PullToRefresh上拉刷新下拉加载

第四篇:整理工程 - 模块化 (敬请期待)

背景:鸿蒙0基础探索。

愿景:本系列旨在用简单直接的方式从让鸿蒙app先从0-1。

理由:有产出更有继续下去的动力。

记录:每篇文章保留下探索的过程。

PS: 不教写代码,不封装,业务代码能力因人而异。(关键我不会啊)

书接上回。我们现在学会了使用Tabs,Navigation,Grid。有了这几件的基础,自然就可以探索网络请求,和模型解析。(这一篇探索完是不是感觉写个小应用没啥问题了。)

探索

说到网络请求,介于iOS经验,第一步我想到的就是使用网络请求的第三方库。(毕竟在项目中,真的很少用自带的直接进行请求)。顺便也尝试一下怎么集成第三方库。

通过搜索鸿蒙第三方库就会找到,

怎么安装包文档

一进来我们就发现了想要的,说明这个探索的路子是没错的。。额外补充一句这个ohos打头的不知道是不是官方维护的,因为看到还有别的知名库。比如lottie。那就愉快的决定使用ohos/axios了。

没有后台支持,接下来我要去找一个免费的API的接口。经过一番搜索。找到了github上免费api集合我挑了其中一个Animals - Cats的。Cats文档, ,填邮箱,会把apikey发送到邮箱。

ps:自己有后台,有其他接口用就不用这么麻烦了。我这就做了示例。

导入Axios,进行网络请求。

axios码云文档 :这个看起来更舒服。

怎么安装包文档中提到了几种安装方式。 我们结合着Axios的文档,选择用终端区安装,如下图所示,导入第三方是不是很简单。

文档上: 需要权限 ohos.permission.INTERNET, 不知道怎么做,老样子,我们先去官方文档上搜索一下,把前几个链接都点开扫一眼,找找关键词。我找到了这个。

于是乎我们也在module.json5中,添加这个配置。记得点Sync Now.

发起请求

发起一个 GET 请求

第三方数据加载失败__下拉刷新上拉加载原理

axios支持泛型参数,由于ArkTS不再支持any类型,需指定参数的具体类型。 如:axios.get(url)

我们现在对这样一个Api发起请求/v1/images/s…ps:返回的列表里图片怎么我用wifi不行,你也不行换几个网络环境试试。

我们不先定义模型,直接去发送请求(也不做任何额外的定义,先看能不能调通才是第一要素),通过log看看输出。

@Entry
@Component
export struct CatSqualPage {
  
  // 页面出现的时候
  aboutToAppear(): void {
    // 去发送请求,
    axios.get("https://api.thecatapi.com/v1/images/search", {params: { limit: "10"} })
      .then((response: AxiosResponse) => {
        console.warn("请求:" + JSON.stringify(response.config));
        console.warn("请求结果result:" + JSON.stringify(response.data));
        console.warn("请求结果类型result:" + typeof response.data );
        // 便利打印
        response.data.forEach(cat => {
          console.warn(`ID: ${cat.id}, URL: ${cat.url}, Width: ${cat.width}, Height: ${cat.height}`);
        });
      })
      .catch((error: AxiosError) => {
        console.error("result:" + error.message);
      });
  }
  build() {
  }
}

能调通

模型解析

那接着我们看看接口返回的数据,想着给他做模型化。不得不说这库对解析的集成,真挺好用。比起iOS来说。

ps: 据说之前版本支持any,接口不需要做模型化也能用。现在Arkts禁用了any。

[
    {
        "id": "140",
        "url": "https://cdn2.thecatapi.com/images/140.gif",
        "width": 293,
        "height": 163
    }
]

结合上两篇我们所学的,用到NavDestination做导航子组件,Grid网格承接模型数据。网络请求成功后,刷新网格的数据,因此涉及到了数据绑定@State.

T,R应该都是泛型的意思。只需要声明一下,response.data就可以直接拿来用,真是方便呢。比如示例中:

axios.get, null>(参数1, 参数2)

示例代码:

import axios, { AxiosRequestConfig, AxiosResponse, AxiosError } from '@ohos/axios'
@Builder
export function CatSqualPageBuilder() {
  CatSqualPage()
}
// 自己创建一个示例,也可以用axios直接调用,我是为了练习,看看能配置些什么。
const gxwAxios = axios.create({
  baseURL: 'https://api.thecatapi.com',
  timeout: 3000,
})
// 实体类(猫的模型)
interface catInfo {
  id: string,
  url: string,
  width: number,
  height: number
}
@Entry
@Component
export struct CatSqualPage {
  // 数据源
  @State modelArray: catInfo[] = []
  // 页面出现的时候
  aboutToAppear(): void {
    // 请求猫的数据
    let config: AxiosRequestConfig = {
      method: 'get',
      params: {
        limit : "10",
        // 这两行注释打开就是另一个接口数据咯
        //breed_ids: "beng",
        //api_key: "live_uRCza6dSXUkli9FSLkPYL24UePJN2b9AD4D7hcanPKTfgV0v3jgS9hkCMd1Dp0bq"
      }
    }
    //
    gxwAxios.getAxiosResponse>("/v1/images/search", config)
      .then((response: AxiosResponse) => {
        console.warn("请求:" + JSON.stringify(response.config));
        console.warn("请求结果result:" + JSON.stringify(response.data));
        console.warn("请求结果类型result:" + typeof response.data );
        this.modelArray = response.data
        // 便利打印
        this.modelArray.forEach(cat => {
          console.warn(`ID: ${cat.id}, URL: ${cat.url}, Width: ${cat.width}, Height: ${cat.height}`);
        });
    })
      .catch((error: AxiosError) => {
        console.error("result:" + error.message);
      });
  }
  build() {
    NavDestination() {
      Column() {
        Grid() {
          ForEach(this.modelArray, (item: catInfo, index) => {
            GridItem() {
              Column() {
                Image(item.url)
                  // 设置占位图。
                  .alt($rawfile('草/c1.png'))
              }
            }
            .height('30%')
          })
        }
        .columnsTemplate('1fr 1fr')
        .rowsGap(10)
        .columnsGap(20)
        .backgroundColor(Color.Yellow)
      }
      .backgroundColor(Color.Red)
    }
  }
}

占位图

经过对文档的一番搜索只在api参考里发现,奇怪的是在指南中为什么没有提这个。通过观察ImageSpan是通过.alt属性设置占位图的,我就试了试Image有没有这个属性,发现是有的。

Image(item.url)
  // 占位图
  .alt($rawfile('火/h1.png'))

上拉加载下拉刷新

接口请求之后,自然就联想到了分页,刷新和加载更多的操作。

遇事不决就搜索搜索刷新关键词其结果都为我们指向了,正巧还能让我再次练习使用第三方库。

PullToRefresh代码文档

网络请求,网格,下拉刷新上拉加载代码都加上会有些凌乱,我们稍微调整一下。

比如:把网络请求写成一个function

ps: 我不会写Pormise或其他,只能模仿着iOS的Block来写。

// MARK: 请求数据
// 请求猫的数据,支持分页的数据。
requestCatsData(page: number, complete: (array: catInfo[]) => void, failure?: (error: AxiosError) => void ) {
  // 参数
  let config: AxiosRequestConfig = {
    method: 'get',
    params: {
      page: page,
      limit : "10",
      // 这两行注释打开就是另一个接口数据咯
      breed_ids: "beng",
      api_key: "live_uRCza6dSXUkli9FSLkPYL24UePJN2b9AD4D7hcanPKTfgV0v3jgS9hkCMd1Dp0bq"
    }
  }
  // 发送请求
  gxwAxios.getAxiosResponse>("/v1/images/search", config)
    .then((response: AxiosResponse) => {
      console.warn("请求:" + JSON.stringify(response.config));
      console.warn("请求结果result:" + JSON.stringify(response.data));
      console.warn("请求结果类型result:" + typeof response.data );
      let result = response.data
      // 便利打印
      result.forEach(cat => {
        console.warn(`ID: ${cat.id}, URL: ${cat.url}, Width: ${cat.width}, Height: ${cat.height}`);
      });
      complete(result)
    })
    .catch((error: AxiosError) => {
      if (failure) {
        failure(error)
      }
    });
}

把网格做成一个@Builder, 这有点像iOS中用一个UIView把控件包装一层注意这个Grid(this.scroller) .edgeEffect(EdgeEffect.None)这两行,我看了文档介入之后上下都拉不动,把PullToRefresh的demo下载下来一点点比才发现是这里。

// 网格
@Builder
creatMyGrid() {
  Grid(**this.scroller**) {
    ForEach(this.modelArray, (item: catInfo, index) => {
      GridItem() {
        Column() {
          Image(item.url)
            // 设置占位图。
            .alt($rawfile('草/c1.png'))
        }
      }
      .height('30%')
    })
  }
  .columnsTemplate('1fr 1fr')
  .rowsGap(10)
  .columnsGap(20)
  .width('100%')
  .height('100%')
  .edgeEffect(EdgeEffect.None)
  .backgroundColor(Color.Yellow)
}