案例:新闻数据加载

文章目录

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

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的使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/320691.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis高并发高可用(主从复制、哨兵)

复制 在分布式系统中为了解决单点问题,通常会把数据复制多个副本部署到其他机器,满足故障恢复和负载均衡等需求。Redis也是如此,它为我们提供了复制功能,实现了相同数据的多个Redis 副本。复制功能是高可用Redis的基础,哨兵和集群都是在复制的基础上实现高可用的。 默认…

C++11 异常

C异常概念 在C中&#xff0c;异常是程序在执行过程中遇到意外情况或错误时抛出的一种机制。当程序运行过程中发生异常&#xff0c;可以通过抛出异常、捕获异常和处理异常来改变程序的正常执行流程。 抛出异常&#xff1a;在程序中&#xff0c;可以使用关键字 throw 来抛出异常…

Android基于Matrix绘制PaintDrawable设置BitmapShader,以手指触点为中心显示原图像圆图,Kotlin(3)

Android基于Matrix绘制PaintDrawable设置BitmapShader&#xff0c;以手指触点为中心显示原图像圆图&#xff0c;Kotlin&#xff08;3&#xff09; 在 Android基于Matrix绘制PaintDrawable设置BitmapShader&#xff0c;以手指触点为中心显示原图像圆图&#xff0c;Kotlin&#…

【小白专用】C# 连接 MySQL 数据库

C# – Mysql 数据库连接 1. 配置环境 #前提&#xff1a;电脑已安装Mysql服务&#xff1b; Visual Studio 安装Mysql依赖库&#xff1a; 工具 -> NuGet 包管理器 -> 管理解决方案的 NuGet程序包 —> 搜索&#xff0c; 安装Mysql.Data (Oracle); (安装成功后&…

libcurl开源库的编译与使用全攻略

libcurl简介 libcurl 是一个广泛使用的、支持多种协议的、开源的客户端URL传输库&#xff0c;提供了许多用于数据传输的API&#xff0c;例如文件传输、FTP、HTTP、HTTPS、SMTP等。libcurl 的主要特点包括 支持多种协议&#xff1a;libcurl 支持多种协议&#xff0c;如 HTTP、F…

【昕宝爸爸小模块】线程的几种状态,状态之间怎样流转

➡️博客首页 https://blog.csdn.net/Java_Yangxiaoyuan 欢迎优秀的你&#x1f44d;点赞、&#x1f5c2;️收藏、加❤️关注哦。 本文章CSDN首发&#xff0c;欢迎转载&#xff0c;要注明出处哦&#xff01; 先感谢优秀的你能认真的看完本文&…

什么是信噪比

大家好&#xff0c;今天给大家介绍什么是信噪比&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 “信噪比”是电子技术中经常用到的一个词组&#xff0c;知道它的确切含义有一定意…

Day02

今日任务&#xff1a; 977 有序数组的平方209 长度最小的子数组59 螺旋矩阵Ⅱ 977 有序数组的平方 题目链接&#xff1a;https://leetcode.cn/problems/squares-of-a-sorted-array/ 双指针问题&#xff0c;以及数组本身时有序的&#xff1b; 思路&#xff1a; 左、右两个…

unet脑肿瘤分割完整代码

U-net脑肿瘤分割完整代码 代码目录数据集网络训练测试 代码目录 数据集 https://www.kaggle.com/datasets/mateuszbuda/lgg-mri-segmentation dataset.py 在这里插入代码片import os import numpy as np import glob from PIL import Image import cv2 import torchvision fr…

如何在“Microsoft Visual Studio”中使用OpenCV构建应用程序

我在这里描述的所有内容都将应用于 OpenCV 的界面。我首先假设您已经阅读并成功完成了 Windows 中的安装教程。因此&#xff0c;在进一步操作之前&#xff0c;请确保您有一个包含 OpenCV 头文件和二进制文件的 OpenCV 目录&#xff0c;并且您已按照此处所述设置环境变量 设置 O…

多智能体强化学习(概念知识,不涉及具体算法)

目录 一、前置知识1.factored value function2.partially observable MDP (POMDP) problem.2.2 Decentralized-POMDP problem2.3 networked decentralized partially observable Markov decision processes (ND-POMDP) problem2.4 上述两种算法的区别 3. Mean Field Multi-Agen…

深信服超融合HCI版本升级,6.0.0R5升级至6.8.0R2

超融合升级&#xff0c;需要满足以下条件及前期准备&#xff1a; 确认HCI的升级序列号有效升级时长大概在一个半小时&#xff0c;安全起见&#xff0c;需预留至少三至四小时窗口期升级前&#xff0c;需要将所有虚拟机关机&#xff0c;涉及到业务无法访问&#xff0c;需提前通知…

redis中的string相关的部分命令

redis命令手册 redis中文官网查看文档 挨个进行输出调试 Redis Setnx 命令 Redis Getrange 命令 Redis Mset 命令 redis 127.0.0.1:6379> MSET key1 "Hello" key2 "World" OK redis 127.0.0.1:6379> GET key1 "Hello" redis 127.0.0.1:…

datavrap-各种各样的条形图(含详细操作步骤)

静态条形图&#xff1a;正确设置数据即可&#xff0c;导出的图形不会随着时间变化 最普通的静态条形图 黑色系风格的静态条形图 动态条形图&#xff1a;导出的图形会随着时间变化 普通的动态条形图 带数字滚动效果的动态条形图 简单的Top排行榜动态条形图 格式更丰富的Top排行榜…

牛客周赛 Round 28 解题报告 | 珂学家 | 组合数学 + 离散化树状数组

前言 整体评价 还是E稍微有点意思&#xff0c;新周赛好像比预期要简单一些, _. 欢迎关注 珂朵莉 牛客周赛专栏 珂朵莉 牛客小白月赛专栏 A. 小红的新周赛 思路: 模拟 #include <bits/stdc.h>using namespace std;int main() {int res 0;for (int i 0; i < 6; i…

【算法练习】leetcode算法题合集之数组和哈希表篇

重建数组&#xff08;高频&#xff09; LeetCode283.移动零 LeetCode283.移动零 双指针&#xff0c;记录已经处理好的序列的尾部 class Solution {public void moveZeroes(int[] nums) {int k 0;for (int i 0; i < nums.length; i) {if (nums[i] ! 0) {swap(nums, i, k)…

【前后端的那些事】开源!前后端环境搭建+树形结构表格实现

文章目录 1. 前后端项目环境搭建2. table-tree2.1 后端准备2.2 前端准备 前言&#xff1a;最近写项目&#xff0c;发现了一些很有意思的功能&#xff0c;想写文章&#xff0c;录视频把这些内容记录下。但这些功能太零碎&#xff0c;如果为每个功能都单独搭建一个项目&#xff0…

Python之Matplotlib绘图调节清晰度

Python之Matplotlib绘图调节清晰度 文章目录 Python之Matplotlib绘图调节清晰度引言解决方案dpi是什么&#xff1f;效果展示总结 引言 使用python中的matplotlib.pyplot绘图的时候&#xff0c;如果将图片显示出来&#xff0c;或者另存为图片&#xff0c;常常会出现清晰度不够的…

前端js写数据结构与算法

1、什么是数据结构与算法 数据结构&#xff1a;是指数据对象中数据元素之间的相互关系。包括集合结构、线性结构、树形结构、图形结构。 算法&#xff1a;解决问题的思路。 2、时间复杂度 1.是什么? 执行当前算法所“花费的时间” 2.干什么? 在写代码的过程中&#xf…

网工内推 | 信息安全主管,CISP/CISSP认证优先,最高25K

01 武汉华康世纪医疗股份有限公司 招聘岗位&#xff1a;网络安全主管 职责描述&#xff1a; 1、推进公司信息/网络安全管理体系规划、建设、持续改进&#xff0c;促进信息安全管理的推行落地,保障网络、系统与数据安全&#xff1b; 2、维护管理信息/网络管理软件&#xff0c;设…