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

案例:新闻数据加载

文章目录

  • 介绍
    • 相关概念
    • 相关权限
    • 约束与限制
    • 完整示例
  • 代码结构解读
  • 构建主界面
  • 数据请求
  • 下拉刷新
  • 总结

img

介绍

本篇Codelab是基于ArkTS的声明式开发范式实现的样例,主要介绍了数据请求和touch事件的使用。包含以下功能:

  1. 数据请求。
  2. 列表下拉刷新。
  3. 列表上拉加载。

相关概念

  • List组件:列表包含一系列相同宽度的列表项。
  • Tabs:通过页签进行内容视图切换。
  • TabContent:仅在Tabs中使用,对应一个切换页签的内容视图。
  • 数据请求:提供HTTP数据请求能力。
  • 触摸事件onTouch:触摸动作触发调用该方法。

相关权限

网络数据请求需要申请权限:ohos.permission.INTERNET。

约束与限制

本篇Codelab需要搭建服务端环境,服务端如何搭建将在代码工程目录的README中详细介绍,文档中不再赘述。

完整示例

gitee源码地址

源码下载

新闻数据加载(ArkTS).zip

代码结构解读

本篇Codelab只对核心代码进行讲解,对于完整代码,我们会在源码下载或gitee中提供。

├──entry/src/main/ets                   // ArkTS代码区
│  ├──common
│  │  ├──constant
│  │  │  └──CommonConstant.ets          // 公共常量类
│  │  └──utils
│  │     ├──HttpUtil.ets                // 网络请求方法
│  │     ├──Logger.ets                  // 日志工具类
│  │     ├──PullDownRefresh.ets         // 下拉刷新方法
│  │     └──PullUpLoadMore.ets          // 上拉加载更多方法
│  ├──entryability
│  │  └──EntryAbility.ts                // 程序入口类
│  ├──pages
│  │  └──Index.ets                      // 主页面
│  ├──view
│  │  ├──CustomRefreshLoadLayout.ets    // 下拉刷新、上拉加载布局文件
│  │  ├──LoadMoreLayout.ets             // 上拉加载布局封装
│  │  ├──NewsItem.ets                   // 新闻数据
│  │  ├──NewsList.ets                   // 新闻列表
│  │  ├──NoMoreLayout.ets               // 上拉停止布局封装
│  │  ├──RefreshLayout.ets              // 下拉刷新布局封装
│  │  └──TabBar.ets                     // 新闻类型页签
│  └──viewmodel
│     ├──NewsModel.ets                  // 新闻模型类
│     └──NewsViewModel.ets              // 新闻ViewModel
├──entry/src/main/resources             // 资源文件目录
└──HttpServerOfNews                     // 服务端代码

构建主界面

本章节将介绍新闻列表页面的实现,用tabBar展示新闻分类,tabContent展示新闻列表,效果图如图所示:

img

在TabBar.ets文件中的aboutToAppear()方法里获取新闻分类。

// TabBar.ets
aboutToAppear() {// 请求服务端新闻类别NewsViewModel.getNewsTypeList().then((typeList: NewsTypeBean[]) => {this.tabBarArray = typeList;}).catch((typeList: NewsTypeBean[]) => {this.tabBarArray = typeList;});
}

在NewsList.ets文件中的aboutToAppear()方法里获取新闻数据,将数据加载到新闻列表页面ListLayout布局中。

// NewsList.ets
changeCategory() {this.newsModel.currentPage = 1;NewsViewModel.getNewsList(this.newsModel.currentPage, this.newsModel.pageSize, Const.GET_NEWS_LIST).then((data: NewsData[]) => {this.newsModel.pageState = PageState.Success;if (data.length === this.newsModel.pageSize) {this.newsModel.currentPage++;this.newsModel.hasMore = true;} else {this.newsModel.hasMore = false;}this.newsModel.newsData = data;}).catch((err: string | Resource) => {promptAction.showToast({message: err,duration: Const.ANIMATION_DURATION});this.newsModel.pageState = PageState.Fail;});
}
aboutToAppear() {// 请求服务端新闻数据this.changeCategory();
}
...
@Builder ListLayout() {List() {...ForEach(this.newsModel.newsData, (item: NewsData) => {ListItem() {// 新闻数据NewsItem({ newsData: item })}.height($r('app.float.news_list_height')).backgroundColor($r('app.color.white')).margin({ top: $r('app.float.news_list_margin_top') }).borderRadius(Const.NewsListConstant_ITEM_BORDER_RADIUS)}, (item: NewsData, index?: number) => JSON.stringify(item) + index)...}...
}

数据请求

在module.json5文件中配置如右侧所示权限:

这一章节,将基于新闻数据请求来介绍如何从服务端请求数据。

// module.json5
"requestPermissions": [{"name": "ohos.permission.INTERNET","reason": "$string:dependency_reason","usedScene": {"abilities": ["EntryAbility"],"when": "inuse"}}
]

导入http模块,封装httpRequestGet方法,调用者传入url地址发起网络数据请求。

// HttpUtil.ets
import http from '@ohos.net.http';
...
export function httpRequestGet(url: string): Promise<ResponseResult> {let httpRequest = http.createHttp();// 发送数据请求let responseResult = httpRequest.request(url, {method: http.RequestMethod.GET,readTimeout: Const.HTTP_READ_TIMEOUT,header: {'Content-Type': ContentType.JSON},connectTimeout: Const.HTTP_READ_TIMEOUT,extraData: {}});let serverData: ResponseResult = new ResponseResult();// 处理数据,并返回return responseResult.then((value: http.HttpResponse) => {Logger.info(`http value ${JSON.stringify(value)}`);if (value.responseCode === Const.HTTP_CODE_200) {// 获取返回数据let result = `${value.result}`;let resultJson: ResponseResult = JSON.parse(result);if (resultJson.code === Const.SERVER_CODE_SUCCESS) {serverData.data = resultJson.data;}serverData.code = resultJson.code;serverData.msg = resultJson.msg;} else {serverData.msg = `${$r('app.string.http_error_message')}&${value.responseCode}`;}return serverData;}).catch(() => {serverData.msg = $r('app.string.http_error_message');return serverData;})
}

在NewsViewModel.ets文件中封装getNewsList方法,调用httpRequestGet方法请求服务端,用Promise异步保存返回的新闻数据列表。

// NewsViewModel.ets
// 获取服务端新闻数据列表
getNewsList(currentPage: number, pageSize: number, path: string): Promise<NewsData[]> {return new Promise(async (resolve: Function, reject: Function) => {let url = `${Const.SERVER}/${path}`;url += '?currentPage=' + currentPage + '&pageSize=' + pageSize;httpRequestGet(url).then((data: ResponseResult) => {if (data.code === Const.SERVER_CODE_SUCCESS) {resolve(data.data);} else {Logger.error('getNewsList failed', JSON.stringify(data));reject($r('app.string.page_none_msg'));}}).catch((err: Error) => {Logger.error('getNewsList failed', JSON.stringify(err));reject($r('app.string.http_error_message'));});});
}

下拉刷新

本章节将以下拉刷新的功能效果来介绍touch事件的使用。效果图如图所示:

img

创建一个下拉刷新布局CustomLayout,动态传入刷新图片和刷新文字描述。

// CustomRefreshLoadLayout.ets
build() {Row() {// 下拉刷新图片Image(this.customRefreshLoadClass.imageSrc)...// 下拉刷新文字Text(this.customRefreshLoadClass.textValue)...}...
}

将下拉刷新的布局添加到NewsList.ets文件中新闻列表布局ListLayout里面,监听ListLayout组件的onTouch事件实现下拉刷新。

// NewsList.ets
build() {Column() {if (this.newsModel.pageState === PageState.Success) {this.ListLayout()}...}....onTouch((event: TouchEvent | undefined) => {if (event) {if (this.newsModel.pageState === PageState.Success) {listTouchEvent(this.newsModel, event);}}})
}
...
@Builder ListLayout() {List() {ListItem() {RefreshLayout({refreshLayoutClass: new CustomRefreshLoadLayoutClass(this.newsModel.isVisiblePullDown, this.newsModel.pullDownRefreshImage,this.newsModel.pullDownRefreshText, this.newsModel.pullDownRefreshHeight)})...}}...
}
  1. 在onTouch事件中,listTouchEvent方法判断触摸事件是否满足下拉条件。如右侧listTouchEvent所示:
  2. 在touchMovePullRefresh方法中,我们将对下拉的偏移量与下拉刷新布局的高度进行对比,如果大于布局高度并且在新闻列表的顶部,则表示达到刷新条件。如右侧touchMovePullRefresh所示:
  3. 在pullRefreshState方法中我们会对下拉刷新布局中的状态图片和描述进行改变,如右侧pullRefreshState所示。
  4. 当手指松开,才执行刷新操作。
// PullDownRefresh.ets
export function listTouchEvent(newsModel: NewsModel, event: TouchEvent) {switch (event.type) {...case TouchType.Move:if ((newsModel.isRefreshing === true) || (newsModel.isLoading === true)) {return;}let isDownPull = event.touches[0].y - newsModel.lastMoveY > 0;if (((isDownPull === true) || (newsModel.isPullRefreshOperation === true)) && (newsModel.isCanLoadMore === false)){// 手指移动,处理下拉刷新touchMovePullRefresh(newsModel, event);}...break;}
}
export function touchMovePullRefresh(newsModel: NewsModel, event: TouchEvent) {if (newsModel.startIndex === 0) {newsModel.isPullRefreshOperation = true;let height = vp2px(newsModel.pullDownRefreshHeight);newsModel.offsetY = event.touches[0].y - newsModel.downY;// 滑动偏移量大于下拉刷新布局高度,满足刷新条件。if (newsModel.offsetY >= height) {pullRefreshState(newsModel, RefreshState.Release);newsModel.offsetY = height + newsModel.offsetY * Const.Y_OFF_SET_COEFFICIENT;} else {pullRefreshState(newsModel, RefreshState.DropDown);}if (newsModel.offsetY < 0) {newsModel.offsetY = 0;newsModel.isPullRefreshOperation = false;}}
}
export function pullRefreshState(newsModel: NewsModel, state: number) {switch (state) {...case RefreshState.Release:newsModel.pullDownRefreshText = $r('app.string.release_refresh_text');newsModel.pullDownRefreshImage = $r('app.media.ic_pull_up_refresh');newsModel.isCanRefresh = true;newsModel.isRefreshing = false;break;case RefreshState.Refreshing:newsModel.offsetY = vp2px(newsModel.pullDownRefreshHeight);newsModel.pullDownRefreshText = $r('app.string.refreshing_text');newsModel.pullDownRefreshImage = $r('app.media.ic_pull_up_load');newsModel.isCanRefresh = true;newsModel.isRefreshing = true;break;case RefreshState.Success:newsModel.pullDownRefreshText = $r('app.string.refresh_success_text');newsModel.pullDownRefreshImage = $r('app.media.ic_succeed_refresh');newsModel.isCanRefresh = true;newsModel.isRefreshing = true;break;...default:break;}
}

上拉加载也是通过touch事件来实现的,此处不再赘叙,有兴趣的同学可参考代码。

总结

您已经完成了本次Codelab的学习,并了解到以下知识点:

  1. 使用List组件实现数据列表。
  2. 使用Tabs、TabContent组件实现内容视图切换。
  3. 网络数据请求。
  4. 触摸事件onTouch的使用。
http://www.lryc.cn/news/280528.html

相关文章:

  • 数学的雨伞下:理解世界的乐趣
  • 补充 vue3用户管理权限(路由控制)
  • C++ 深度优先搜索DFS || 模版题:排列数字
  • 计算机找不到msvcp120.dll如何解决?总结五个可靠的教程
  • 法线变换矩阵的推导
  • React.Children.map 和 js 的 map 有什么区别?
  • 13.Kubernetes部署Go应用完整流程:从Dockerfile到Ingress发布完整流程
  • 叉车车载终端定制_基于MT6762安卓核心板的车载终端设备方案
  • 【CSS】保持元素宽高比
  • 使用 Docker 和 Diffusers 快速上手 Stable Video Diffusion 图生视频大模型
  • C++ namespace高级用法
  • 如何允许远程访问 MySQL
  • PostgreSQL认证考试PGCA、PGCE、PGCM
  • Matlab深度学习进行波形分割(二)
  • Markdown高级用法——mermaid
  • cf919Div2C题题目总结
  • Pandas实战100例 | 案例 4: 数据选择和索引 - 选择特定的列和行
  • Netty-Netty实现自己的通信框架
  • 【算法刷题】总结规律 算法题目第2讲 [234] 回文链表,因为深浅拷贝引出的bug
  • RabbitMQ如何保证消息不丢失?
  • Random的使用
  • 通过反射修改MultipartFile类文件名
  • Macos下修改Python版本
  • 多种采购方式下,数智化招标采购系统建设解决方案
  • Java选择排序
  • [足式机器人]Part3 机构运动学与动力学分析与建模 Ch00-1 坐标系与概念基准
  • 【金猿人物展】DataPipelineCEO陈诚:赋能数据应用,发挥未来生产力
  • 4D 毫米波雷达:智驾普及的新路径(二)
  • element plus自定义组件表单校验
  • C //练习 4-13 编写一个递归版本的reverse(s)函数,以将字符串s倒置。