赞
踩
本篇Codelab是基于ArkTS的声明式开发范式实现的样例,主要介绍了数据请求和touch事件的使用。包含以下功能:
添加网络权限:ohos.permission.INTERNET。
搭建nodejs环境:本篇Codelab的服务端是基于nodejs实现的,需要安装nodejs,如果您本地已有nodejs环境可以跳过此步骤。
检查本地是否安装nodejs:打开命令行工具(如Windows系统的cmd和Mac电脑的Terminal,这里以Windows为例),输入node -v,如果可以看到版本信息,说明已经安装nodejs。
如果本地没有nodejs环境,您可以去nodejs官网上下载所需版本进行安装配置。
配置完环境变量后,重新打开命令行工具,输入node -v,如果可以看到版本信息,说明已安装成功。
构建局域网环境:测试本Codelab时要确保运行服务端代码的电脑和测试机连接的是同一局域网下的网络,您可以用您的手机开一个个人热点,然后将测试机和运行服务端代码的电脑都连接您的手机热点进行测试。
运行服务端代码:在本项目的HttpServerOfNews目录下打开命令行工具,输入npm install 安装服务端依赖包,安装成功后输入npm start点击回车。看到“服务器启动成功!”则表示服务端已经在正常运行。
连接服务器地址:打开命令行工具,输入ipconfig命令查看本地ip,将本地ip地址复制到src/main/ets/common/constant/CommonConstants.ets文件下的23行,注意只替换ip地址部分,不要修改端口号,保存好ip之后即可运行Codelab进行测试。
完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:
获取OpenHarmony系统版本:标准系统解决方案(二进制)。以3.2Release版本为例:
搭建烧录环境。
搭建开发环境。
本篇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展示新闻列表,效果图如图所示:
在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事件的使用。效果图如图所示:
创建一个下拉刷新布局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)
- })
- ...
- }
- }
- ...
- }
- // 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事件来实现的,此处不再赘叙,有兴趣的同学可参考代码。
有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。
这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。
希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!
如果你是一名有经验的资深Android移动开发、Java开发、前端开发、对鸿蒙感兴趣以及转行人员,可以直接领取这份资料
获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
HarmonOS基础技能
有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。
获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
OpenHarmony北向、南向开发环境搭建
获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。