当前位置: 首页 > news >正文

鸿蒙App开发 HarmonyOS:网络请求+三方库使用+底栏切换+列表+Banner

本篇的大致内容如下:

  1. 效果展示
  2. 知识点分解
  3. 具体实现
  4. 最后总结

一. 效果展示

二. 知识点分解

1. 基础组件使用

  • Tabs + TabContent

以Tabs组件为基础,其中有2个TAB分别展示了“首页”TAB和“项目”TAB,本例中项目TAB下无内容。仅作为展示Tabs组件所用。

Tabs通过页签进行内容视图切换的容器组件,每个页签对应一个内容视图。 需要配合TabContent组件使用,TabContent仅在Tabs中使用,对应一个切换页签的内容视图。

  • Swiper

首页顶部放置的Swiper组件, 滑块视图容器,提供子组件滑动轮播显示的能力。

  • Web

提供具有网页显示能力的Web组件,@ohos.web.webview 提供web控制能力。

2. 页面跳转

@system.router (页面路由) 通过不同的uri访问不同的页面。

本例中,在点击Swiper组件内容或文章列表项后,跳转到应用内的Web页面。

3. 网络请求

@ohos.net.http (数据请求)

参考鸿蒙官方sample代码,对http数据请求进行了简单封装。可以进行get类型的请求发送。

4. 引入三方库

由于鸿蒙原生List控件并没有下拉刷新和上拉加载功能,并且在开发者官网给出支持下拉刷新和上拉加载的demo使用起来并不方便。所以本例中使用了三方库,该引入的三方库在实现列表下拉和上拉操作时会方便许多。

这也是三方库能够加速app开发的重要特性。 本例中就以引入该三方列表库来展示如何在鸿蒙开发中引入静态三方库。

三. 具体实现

首先需要建立首页结构。在MainPage中加入Tabs组件,在Tabs中加入TabContent.

@Builder TabBuilder(title: string, index: number, icon: Resource) {Column() {Image(icon).width($r('app.float.mainPage_baseTab_size')).height($r('app.float.mainPage_baseTab_size')).fillColor(this.getTabBarColor(index))Text(title).margin({ top: $r('app.float.mainPage_baseTab_top') }).fontSize($r('app.float.main_tab_fontSize')).fontColor(this.getTabBarColor(index))}.justifyContent(FlexAlign.Center).height($r('app.float.mainPage_barHeight')).width(Constants.FULL_PARENT).onClick(() => {this.currentTabIndex = index;this.tabsController.changeIndex(this.currentTabIndex)})
}build() {Tabs({barPosition: BarPosition.End,controller: this.tabsController}) {// 首页TabContent() {Home()}.padding({ left: $r('app.float.mainPage_padding'), right: $r('app.float.mainPage_padding') }).backgroundColor($r('app.color.mainPage_backgroundColor')).tabBar(this.TabBuilder(Constants.HOME_TITLE, Constants.HOME_TAB_INDEX, $r('app.media.ic_bottom_home')))// 项目TabContent() {Project()}.padding({ left: $r('app.float.mainPage_padding'), right: $r('app.float.mainPage_padding') }).backgroundColor($r('app.color.mainPage_backgroundColor')).tabBar(this.TabBuilder(Constants.PROJECT_TITLE, Constants.PROJECT_TAB_INDEX, $r('app.media.ic_bottom_project')))}.width(Constants.FULL_PARENT).backgroundColor(Color.White).barHeight($r('app.float.mainPage_barHeight')).barMode(BarMode.Fixed).onChange((index: number) => {this.currentTabIndex = index;})
}

Home中由一个Banner自定义组件和ArticleList自定义组件构成

@Component
export default struct Home {build() {Stack() {ArticleList();Banner();}.alignContent(Alignment.Top)}
}

Banner组件中进行Banner数据请求并填充到Swiper组件中。

aboutToAppear生命周期中进行了请求发送。

对于组件的 aboutToAppear 和 aboutToDisappear 在开发过程中会比较常用到。

aboutToAppear

aboutToAppear?(): void

aboutToAppear函数在创建自定义组件的新实例后,在执行其build函数之前执行。允许在aboutToAppear函数中改变状态变量,更改将在后续执行build函数中生效。

aboutToDisappear

aboutToDisappear?(): void

aboutToDisappear函数在自定义组件析构销毁之前执行。不允许在aboutToDisappear函数中改变状态变量,特别是@Link变量的修改可能会导致应用程序行为不稳定。

点击Banner项时将进行页面跳转

aboutToAppear() {HomeViewModel.getHomeBanner(Constants.GET_HOME_BANNER).then((data: HomeBannerItemBean[]) => {this.bannerData = data;}).catch((err: string | Resource) => {promptAction.showToast({message: err,duration: Constants.ANIMATION_DURATION});});
}build() {Column() {Swiper(this.swiperController) {ForEach(this.bannerData, (banner: HomeBannerItemBean) => {Image(banner.imagePath).borderRadius($r('app.float.home_swiper_borderRadius')).onClick(() => {router.pushUrl({url: 'pages/WebPage',params: {title: banner.title,src: banner.url}}, router.RouterMode.Single)})}, (img: Resource) => JSON.stringify(img.id))}.margin({top: $r('app.float.home_swiper_margin')}).autoPlay(true).width(Constants.FULL_PARENT).height($r('app.float.main_swiper_height'))}
}

文章列表实现, 也是在aboutToAppear中进行数据请求。可以看到这里使用的三方组件ListView很轻松的实现了目标功能。

aboutToAppear() {this.getHomeArticleList(true);
}@Builder
itemLayout(item, index) {ArticleItem({articleData: item})
}getHomeArticleList(reset: boolean) {HomeViewModel.getHomeArticleList(this.currentPage, this.pageSize, Constants.GET_HOME_ARTICLE_LIST).then((data: ArticleDataBean) => {if (data.curPage < data.pageCount) {this.currentPage++;this.hasMore = true;}  else {this.hasMore = false;}if (reset) {this.articleData = data.datas;} else {this.articleData = this.articleData.concat(data.datas);}}).catch((err: string | Resource) => {promptAction.showToast({ message: err});})
}build() {ListView({items: this.articleData, //数据源 数组itemLayout: (item, index) => this.itemLayout(item, index),controller: this.controller, //控制器,负责关闭下拉和上拉marginHeader: 160,onRefresh: () => {//下拉刷新this.getHomeArticleList(true);this.controller.finishRefresh()},onLoadMore: () => {//上拉加载this.getHomeArticleList(false);this.controller.finishLoadMore()}})
}

新建WebPage, 封装Web组件实现网页的展示。 WebPage接受src参数作为页面url, 接受title参数作为标题栏文字。

import router from '@ohos.router';
import web_webview from '@ohos.web.webview'
import Constants from '../common/Constants';@Entry
@Component
struct WebPage {@State src: string = router.getParams()?.['src'];@State title: string = router.getParams()?.['title'];controller: web_webview.WebviewController = new web_webview.WebviewController();build() {Column() {PageTitle({ titleName: this.title })Divider().strokeWidth('1px').color($r('sys.color.ohos_id_color_list_separator'))Web({src: this.src, controller: this.controller}).javaScriptAccess(true)}}
}@Component
struct PageTitle {private titleName: stringbuild() {Row() {Image($r('app.media.back')).width(20).height(20).onClick(() => {router.back()})Text(this.titleName).fontSize(Constants.PAGE_TITLE_TEXT_SIZE).width(Constants.PAGE_TITLE_TEXT_WIDTH).maxLines(Constants.PAGE_TITLE_TEXT_MAX_LINES).textOverflow({overflow: TextOverflow.Ellipsis}).margin({ left: 20 })}.padding(12).width('100%')}
}

别忘记在pages配置中添加WebPage页面

该配置位于ets/resources/base/profile/main_pages.json

{"src": ["pages/MainPage","pages/WebPage"]
}

网络请求方法封装, 实际项目中可以考虑换成其他三方库来实现网络请求。以实现Header拦截,error拦截等操作,以及其他如post类型等其他常见需求。

本例中使用的开放接口来自WanAndroid大神的无私奉献,此例中仅使用了2个接口。大家如有兴趣可以参考并自行实现全部接口。

感谢鸿洋大佬的WanAndroid网站提供的 传送门

/*** Initiates an HTTP request to a given URL.** @param url URL for initiating an HTTP request.* @param params Params for initiating an HTTP request.*/
export function httpRequestGet(url: string): Promise<ResponseResult> {let httpRequest = http.createHttp();let responseResult = httpRequest.request(url, {method: http.RequestMethod.GET,readTimeout: Constants.HTTP_READ_TIMEOUT,header: {'Content-Type': ContentType.JSON},connectTimeout: Constants.HTTP_READ_TIMEOUT,extraData: {}});let serverData: ResponseResult = new ResponseResult();// Processes the data and returns.return responseResult.then((value: http.HttpResponse) => {if (value.responseCode === Constants.HTTP_CODE_200) {// Obtains the returned data.let result = `${value.result}`;let resultJson: ResponseResult = JSON.parse(result);if (resultJson.errorCode === Constants.SERVER_CODE_SUCCESS) {serverData.data = resultJson.data;}serverData.errorCode = resultJson.errorCode;serverData.errorMsg = resultJson.errorMsg;} else {serverData.errorMsg = `${$r('app.string.http_error_message')}&${value.responseCode}`;}return serverData;}).catch(() => {serverData.errorMsg = $r('app.string.http_error_message');return serverData;})
}

介绍下三方库的引入方法:

目前可以使用静态包下载后拷贝到项目中的方法来实现引入三方库。 首先在entry目录下新建一个文件夹,比如libs。将下载的har包复制进去。 然后打开entry目录下的oh-package.json5文件。在dependencies字段中填入引入的har包的地址。

完成之后进行一次sync操作。引入的三方静态包将会被以代码形式加入到项目中。

四. 最后总结

鸿蒙基础UI组件使用+页面跳转+网络数据请求+三方组件引入,这一套基础操作在着手去写App时是必不可少的。 熟练掌握后便可继续探索鸿蒙开发。刚开始还比较粗糙请多包涵!

为了能让大家更好的学习鸿蒙 (Harmony OS) 开发技术,这边特意整理了《鸿蒙 (Harmony OS)开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙 (Harmony OS)开发学习手册》

入门必看:https://qr21.cn/FV7h05

  1. 应用开发导读(ArkTS)
  2. 应用开发导读(Java)

HarmonyOS 概念:https://qr21.cn/FV7h05

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. 构建第一个JS应用
  4. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

相关文章:

  • Python 错误 TypeError: __str__ Returned Non-String but Printing Output
  • Redis中缓存穿透、击穿、雪崩以及解决方案
  • PHP如何实现邮箱验证
  • 如何解决ajax浏览器缓存
  • 微信小程序保存二维码的过程
  • 构建第一个ArkTS应用(纯HarmonyOS应用)
  • 打印菱形图案C语言
  • C++服务器 支持http、tcp protobuf、websocket,linux开源框架 零依赖轻松编译部署 Reactor
  • SCAU:前一个和后一个字符
  • JAVA代码优化:Easy Excel(操作Excel文件的开源工具)
  • 基于ssm Vue的戒烟网站源码和论文
  • 实时流式计算 kafkaStream
  • 【算法思考记录】力扣2653. 滑动子数组的美丽值【C++,滑动窗口】
  • 【算法】希尔排序
  • HR看好的字符函数和字符串处理函数!!!
  • Apache的80端口被占用以及访问时报错403
  • classpath对获取配置文件的影响
  • Cumulo 的 ClojureScript 模块已经成型
  • ES6之路之模块详解
  • ESLint简单操作
  • gcc介绍及安装
  • HTTP--网络协议分层,http历史(二)
  • Markdown 语法简单说明
  • mockjs让前端开发独立于后端
  • node入门
  • PHP 7 修改了什么呢 -- 2
  • PHP的类修饰符与访问修饰符
  • 闭包--闭包作用之保存(一)
  • 服务器从安装到部署全过程(二)
  • 给Prometheus造假数据的方法
  • 面试遇到的一些题
  • 扑朔迷离的属性和特性【彻底弄清】
  • 使用前端开发工具包WijmoJS - 创建自定义DropDownTree控件(包含源代码)
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • 我感觉这是史上最牛的防sql注入方法类
  • 新手搭建网站的主要流程
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • 不要一棍子打翻所有黑盒模型,其实可以让它们发挥作用 ...
  • !!【OpenCV学习】计算两幅图像的重叠区域
  • # Apache SeaTunnel 究竟是什么?
  • #define与typedef区别
  • #stm32驱动外设模块总结w5500模块
  • #数学建模# 线性规划问题的Matlab求解
  • (5)STL算法之复制
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (论文阅读26/100)Weakly-supervised learning with convolutional neural networks
  • (转)iOS字体
  • **登录+JWT+异常处理+拦截器+ThreadLocal-开发思想与代码实现**
  • *p=a是把a的值赋给p,p=a是把a的地址赋给p。
  • . Flume面试题
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .equals()到底是什么意思?
  • .NET Core日志内容详解,详解不同日志级别的区别和有关日志记录的实用工具和第三方库详解与示例