news 2026/9/11 2:09:42

HarmonyOS 4新闻APP开发:ArkTS构建列表与详情页

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HarmonyOS 4新闻APP开发:ArkTS构建列表与详情页

简介:基于HarmonyOS 4的新闻类App源代码"hongmeng-headlines",面向初入鸿蒙生态的移动端开发者,旨在以真实项目串联UI搭建、数据通信与设备协同等核心技能。项目基于DevEco Studio构建,包含完整的新闻列表与文章详情界面,适合系统学习鸿蒙应用从零到一的工程实践,也可作为课程设计或毕业设计的参考。压缩包内共78个文件,以ets界面逻辑、json5/json配置为主,辅以svg/png图标、ts构建脚本及tgz依赖,整体仅22.75MB,目录按模块划分,便于逐段研读。目前已有1447人学习下载。通过源码可掌握组件化布局、界面设计、网络请求与JSON解析、本地数据存储、事件监听、生命周期管理、多设备适配、权限申请乃至分布式协同等关键知识点;同时项目提供了清晰的基础模板,便于在此基础上扩展推荐、搜索等个性化新闻功能,兼具教学与二次开发价值。

1. 为什么是 HarmonyOS 4:新闻类 APP 的生态卡位与技术起点

新闻类 APP 是移动端最普及、也最容易写僵的品类,但如果在 HarmonyOS 4 上从零搭一套可编译的源代码,反而比聊天、支付这类应用更轻——不碰复杂传感器、不依赖私有系统服务,核心链路就是网络请求、列表渲染、Web 详情页三条线。下面顺着这三条线,以 API 10 为基线,用 ArkTS 串成一个最小可运行工程:先定 Stage 模型下的模块边界,再解决数据从哪来、列表怎么不卡、详情页怎么承接,最后走到上架前的调试与自检。适合准备过 HarmonyOS 应用基础认证、想直接看代码落点的开发者,也适合评估新闻类 App 迁移成本的客户端团队。

2. HarmonyOS 4 新闻 APP 的代码骨架:Stage 模型、模块划分与数据流设计

拿到需求先别急着写 List。新闻类 App 会在冷启动、切后台、首屏加载三个场景被用户反复考验,这决定了代码骨架先于功能细节。HarmonyOS 4 把所有应用入口收敛到 Stage 模型,不少从 FA 模型迁过来的工程会在这一步返工。

2.1 为什么 Stage 模型是新闻类 App 的默认起点

Stage 模型把应用入口拆成 UIAbility 与 ExtensionAbility 两类能力。新闻客户端只需要一个主界面入口,用 UIAbility 就够,启动方式配成 singleton,避免用户从桌面图标、最近任务、推送通知三个入口进来时拉起多份页面栈。module.json5 里和新闻场景直接相关的四个字段如下,改动之前先读一遍。

{ "module": { "name": "entry", "type": "entry", "abilities": [ { "name": "EntryAbility", "srcEntry": "./ets/entryability/EntryAbility.ets", "launchType": "singleton", "skills": [ { "entities": ["entity.system.home"], "actions": ["action.system.home"] } ] } ] } }

launchType 默认是 singleton,不建议为了“多窗口”改成 multiton。新闻场景没有多开诉求,multiton 会让每次点击图标都新建一个 Ability,返回键行为变得混乱。skills 里保留 Home 入口即可,推送通知的跳转在 onNewWant 回调里做二次分发,不需要注册多条 skill。

冷启动路径上还有一件事:EntryAbility 的 onWindowStageCreate 里只做窗口加载,把网络服务这类全局依赖放到 Ability 的成员变量里初始化,不要放在页面组件内部。页面组件随路由销毁重建,而网络层希望只存在一份。

2.2 新闻模块的工程目录与最小代码结构

entry/src/main/ets/ ├── entryability/EntryAbility.ets ├── pages/ │ ├── Index.ets │ └── NewsDetail.ets ├── model/ │ └── NewsModels.ets ├── network/ │ ├── NewsService.ets │ └── HttpWrapper.ets ├── components/ │ ├── NewsList.ets │ └── NewsListItem.ets └── common/ └── Constants.ets

这个划分刻意不引入 router 层。页面少时,路由跳转直接用页面路由的 pushUrl 按字符串路径管理,等页面超过五个再抽象路由表。model 只放类型定义和序列化方法,network 只负责请求和解析,components 里的 NewsListItem 接收一个 NewsItem 对象,不直接触碰网络层。

目录职责变更频率
model定义 NewsItem、NewsChannel、分页结构
network请求、超时、重试、错误归一
components列表卡片、骨架屏、图片占位
pages组装页面状态与生命周期

变更频率最高的是 components,信息流的卡片样式迭代基本都集中在这里。model 和 network 要尽量稳定,接口响应结构变了,顶多改改 model 字段,UI 层不动。

2.3 数据流设计:从接口到 ListItem 的状态流转

常见做法是给列表页做一个 ViewModel 容器,把加载中、加载成功、加载失败、加载更多四个状态收拢到一个可观察对象里。这个容器不持有 ArkUI 组件,只持有业务数据,页面通过 @State 持有容器的引用。

class NewsFeedState { items: NewsItem[] = [] isLoading: boolean = false errorMsg: string = '' page: number = 1 hasMore: boolean = true }

页面在 onPageShow 里触发首次加载,加载完成后整体赋值 items。不要在 NewsListItem 里各自发请求,否则快速滑动时请求数量会失控。分页页码就放在容器里,滑动到底部时只做 page+1 的增量请求,新数据追加到 items 尾部。

ViewModel 别放进自定义组件。组件销毁后数据跟着清空,从详情页返回列表时又会重新拉接口,新闻流用户一天要进出详情页几十次,重复请求量很可观。把容器放到 EntryAbility 的应用级单例里,或者用 AppStorage 做跨页面缓存,都比绑定在页面生命周期上可控。

3. 拿到新闻数据的三种方式:RSS 解析、JSON 接口与本地 Mock 数据

新闻类 APP 开发早期最大的变量不是 UI 而是数据源。标题里“源代码”三个字让人以为核心是界面代码,实际上一个能演示的新闻 App,八成时间在跟数据格式打交道。三种数据源最常用,按接入成本排个序。

3.1 三种数据源的选型与适用阶段

数据源格式适合阶段主要成本
RSS 2.0XML快速验证阅读体验字段少、无图片尺寸、编码杂
开放新闻 APIJSON产品原型与内测需要申请 Key、有配额限制
本地 MockJSON 文件开发期与 UI 联调需维护假数据,易与真实接口脱节

RSS 内容老一点,但胜在即时可得,找两三个科技或财经博客的 feed,先用真数据把排版调好,再去接开放 API。不建议一上来就接大厂的新闻接口,申请流程和限流规则会拖慢首屏联调。RSS 本质是 XML,ArkTS 里用 @ohos.convertxml 的 ConvertXML 类把 feed 转成对象,再取 title、description、pubDate 字段,够搭一个阅读器原型。商用场景不推荐 RSS,很多站点在图片上做防盗链,列表页会缺图。

本地 Mock 经常被忽略。写一个挂在 assets 下的 news-mock.json,字段结构和真实接口保持一致,前端先把加载态、空态、失败态全部走通,后端接口联调时才不会互相等。

3.2 用 ArkTS 解析 JSON 新闻数据的最小实现

开放新闻 API 通常返回固定结构:错误码、数据列表、分页信息。先把响应体声明成类型,再解析,这一步不要偷懒。

export interface NewsItem { id: number title: string summary: string source: string publishTime: string imageUrl: string contentUrl: string } export interface NewsResponse { code: number message: string data: { list: NewsItem[] hasMore: boolean nextPage: number } }

然后用 HttpWrapper 封装 @ohos.net.http。下面这段是请求函数的核心,超时时间、请求头、错误处理都集中在这里:

import http from '@ohos.net.http' export class NewsService { async fetchNews(page: number): Promise<NewsItem[]> { const httpRequest = http.createHttp() try { const resp = await httpRequest.request( `${Constants.BASE_URL}/news?page=${page}&size=20`, { method: http.RequestMethod.GET, connectTimeout: 10000, readTimeout: 10000, header: { 'Content-Type': 'application/json' } } ) const body = JSON.parse(resp.result as string) as NewsResponse if (body.code !== 0) throw new Error(`api error ${body.code}`) return body.data.list } finally { httpRequest.destroy() } } }

三个参数值得细说。第一,createHttp 创建的实例用完必须 destroy,复用全局实例在长时间运行后可能遇到连接无响应,日志里表现为 promise 一直 pending。第二,connectTimeout 与 readTimeout 在新闻场景建议都设 10 秒,首屏数据超过 3 秒用户就流失,但把超时压到 3 秒又会在弱网下频繁失败,客户端做一次重试并记录第一次失败原因,比盲目缩短超时有效。第三,resp.result 默认是字符串,务必先 JSON.parse 再断言成 NewsResponse,直接强转会在字段缺失时拿到 undefined,后续列表渲染直接崩。

3.3 配置网络权限与明文流量:跑真机前必做的两处修改

真机跑新闻 App 第一步遇到请求报 2300006 错误码,多半是网络权限没给。HarmonyOS 4 在 module.json5 里声明权限,不在页面代码里做动态申请。

{ "module": { "requestPermissions": [ { "name": "ohos.permission.INTERNET" } ], "metadata": [ { "name": "network_security_config", "resource": "$profile:network_config" } ] } }

如果接口地址是 http 明文,还需要放行明文流量。在 resources/base/profile/network_config.xml 里写:

<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="true"> <trust-anchors> <certificates src="system" /> </trust-anchors> </base-config> </network-security-config>

metadata 里 network_security_config 这个 key 是固定的,resource 指向 profile 目录下的 xml 文件名,不要写到 rawfile。正式切 https 后,这段配置可以整段拿掉。调试时加载 DevEco 的 Log 面板,过滤 ohos.net.http 能看到每个请求的失败行,2300006 在权限缺失时出现频率最高,其次是设备网络不可达,按日志顺序排查比盲改代码快。真机请求报证书校验失败时,先看系统时间是否准确,证书校验在时间跳变的设备上会先失败。

4. ArkUI 渲染新闻列表与详情页:List、Web 组件与图片缓存

列表渲染是新闻类 APP 体验的分水岭。方案一:Scroll 加 ForEach 硬渲染,数据量小的时候没问题,新闻流数据几百条起步,内存上涨明显。方案二:直接用 List 加 LazyForEach,只渲染可视区域,这是 HarmonyOS 4 下新闻列表的默认解法。

4.1 新闻列表用 LazyForEach 实现懒加载

先写一个实现 IDataSource 的数据源类,它负责告诉 List 总共多少条、每条数据是什么,以及在数据追加时发通知。

class NewsDataSource implements IDataSource { private items: NewsItem[] = [] private listeners: DataChangeListener[] = [] totalCount(): number { return this.items.length } getData(index: number): NewsItem { return this.items[index] } registerDataChangeListener(listener: DataChangeListener): void { this.listeners.push(listener) } unregisterDataChangeListener(listener: DataChangeListener): void { const idx = this.listeners.indexOf(listener) if (idx >= 0) this.listeners.splice(idx, 1) } addItems(newItems: NewsItem[]): void { const start = this.items.length this.items.push(...newItems) this.listeners.forEach(l => l.onDataAdd(start, newItems.length)) } }

这个类把新增数据的通知封装成 onDataAdd,让 LazyForEach 增量刷新而不是全量重建。页面里这样组装 List:

List({ space: 12, scroller: this.scroller }) { LazyForEach(this.dataSource, (item: NewsItem) => { ListItem() { NewsListItem({ item: item }) } }, (item: NewsItem) => `${item.id}_${item.publishTime}`) } .cachedCount(4) .onReachEnd(() => this.loadMore())

LazyForEach 的第三个参数是键值生成函数,必须能区分每条数据。用索引当 key 会导致插入或删除时复用错乱,新闻流常有置顶、移除操作,所以用 id 加时间戳组合。cachedCount(4) 表示首屏方向多缓存 4 条,减少回滑白屏;调到 10 不会让内存显著上涨,但再大就失去懒加载意义了,滑出屏幕的图片迟迟不释放。onReachEnd 在滚动到底部时触发分页。

4.2 新闻详情页用 Web 组件承载富文本

新闻详情最常见的数据形态是服务端下发的 HTML 片段或整页链接。原生解析 HTML 成本高,图片、排版、字体都难还原,详情页用 Web 组件加载 contentUrl 是行业统一做法。

Web({ src: this.contentUrl, controller: this.controller }) .domStorageAccess(true) .javaScriptAccess(true) .onErrorReceive((event) => { this.errorVisible = true }) .onHttpErrorReceive((event) => { console.error(`http error: ${event.response.getResponseCode()}`) })

两个点要注意。第一,domStorageAccess 要开,部分新闻站点的懒加载脚本依赖 localStorage。第二, Web 页里用户滚动很多屏后返回,再次进入会重建并回到顶部,这是正常行为,不需要做滚动位置恢复,否则内存维护会变复杂。

阅读字号是新闻 App 的高频设置项,但设置方式要区分场景:列表页的字号绑一个 @State 驱动 Text 组件没问题,详情页的字号要等页面加载完成后注入给 H5。

this.controller.runJavaScript(` document.body.style.fontSize = '${this.fontSize}px'; `)

runJavaScript 必须在 onPageEnd 回调之后再调用,页面没加载完会报错。有些站点正文不是直接挂在 body 下,需要再查一下文章容器的选择器,这里只提供一个通用注入入口。

4.3 图片加载:占位图与内存控制

列表卡片一般都有缩略图。Image 组件的加载、解码和缓存由系统接管,开发阶段不需要引入三方图片库,但两个参数要设置到位:

Image(item.imageUrl) .width(120) .height(80) .objectFit(ImageFit.Cover) .alt($r('app.media.placeholder')) .onError(() => { this.showErrorPlaceholder = true })
参数作用建议值
objectFit图片缩放模式Cover,避免变形
alt加载中与失败占位图本地资源
onError加载失败回调切本地图或隐藏

不要用 ImageFit.Contain,新闻缩略图是固定宽高比裁剪,Contain 会留白,卡片视觉上参差。图片 URL 的域名有条件的话加进 network_config 的 domain-config,省一次跳转等待。列表页面的加载更多状态建议单独放一个 footer 组件,滚动到底部时显示转圈,避免用弹窗打断滑动。

5. 从源代码到上架:抓包排查、性能数据与发布前自检

代码写完之后,从源代码到可发布版本之间还有一段路。这一章把调试、性能和上架前必须做的手续集中梳理一遍,都是可复现的操作。

5.1 新闻 App 抓包失败的三个排查点

开发期抓包失败是最常见的求助场景。出现抓不到新闻请求时,按下面顺序查,能省下大量排查时间:

  1. 设备与抓包工具是否在同一网络。不在同一网段时流量根本过不去,这是第一排查点。
  2. 抓包证书是否装进系统信任区。只装用户证书时,部分新闻接口在 HTTP/2 下会保持连接不触发抓包。
  3. 目标接口是否为 HTTPS。证书没配对前只能看到连接握手,看不到 HTTP 层内容。

排查完这三项还抓不到,把 App 完全杀掉重开。新闻类接口不少在启动后几秒内并发请求,抓包工具的过滤条件设得过窄时容易漏掉。抓包的目的不是截取数据,而是确认请求头、响应体和缓存策略是否符合预期。

5.2 用 DevEco Profiler 看列表性能

信息流卡顿不要凭感觉。DevEco Studio 的 Profiler 面板可以抓 ArkUI 渲染帧耗时。打开 Profiler 后操作列表快速滑动,观察 Frame 和 Layout 两个指标。

指标关注点合格线
Frame平均帧耗时低于 16ms
Layout列表项布局时间单帧不超过 8ms
Memory图片与 Web 缓存占用占用不持续上涨

如果 Layout 超时,优先检查 NewsListItem 里是否有不必要的 @State。放在子组件里但从不改动的字段,不要用 @State 修饰,多余的装饰器会让整棵子树参与 diff。Profiler 里能看到每个自定义组件的创建耗时,卡片创建超过 3ms 就该拆静态模板了。

5.3 源码版本管理与发布前自检

源代码与原始版本脱钩是二次修改的前提。调试用的 BASE_URL 不能进发布包,由构建脚本替换,或者维护一个单独的常量文件,发布前只动这一处:

// common/ProfileConfig.ets export class ProfileConfig { static readonly BASE_URL: string = 'https://debug.news.example.com' // 发布前切换为 release 地址,并由构建脚本注入 }

调试包和发布包不要维护两套代码,否则容易在发版时选错配置。发布前再走一遍这六项:权限只留 INTERNET,不开存储与位置权限;隐私政策里写清采集哪些字段;深色模式下列表卡片对比度足够;断网时有错误提示而不是白屏;连续启动退出三次无崩溃;通过 HarmonyOS 应用基础认证后再提交审核。最后在 DevEco 里打 release 包,用正式 keystore 签名,勾选混淆开关。提交前的动作是卸载设备上的调试签名旧包再装正式包,签名冲突会导致安装失败,登录态和推送通道各跑一遍,确认后走发布流程。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 2:09:41

SDD规范驱动开发:用三份结构化文档替代口头对齐

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 2:09:31

多模态视觉大模型实战:从融合原理到Agent应用开发指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 2:09:27

数字孪生技术架构与6G时代的应用实践

1. 数字孪生技术全景解析数字孪生&#xff08;Digital Twin&#xff09;作为物理实体在虚拟空间的动态映射&#xff0c;正在重塑工业制造、城市管理等诸多领域的技术范式。这项技术的核心在于通过传感器、物联网设备实时采集物理对象数据&#xff0c;在虚拟环境中构建高保真模型…

作者头像 李华
网站建设 2026/9/11 2:03:31

舰船目标检测YOLO数据集与多版本训练部署实战

简介&#xff1a;本资源是面向计算机视觉初学者与YOLO系列算法实践者的多类别船舶目标检测专用数据集&#xff0c;适用于YOLOv5/v7/v8/v9/v10/v11等主流版本的模型训练、验证与测试。数据集共12122张航空影像&#xff0c;涵盖航空母舰、潜水艇、游船、集装箱船、猛拉&#xff0…

作者头像 李华
网站建设 2026/9/11 2:03:12

wno_interface微型接口配置管理器

一、简介 wno_interface 是一款微型的接口配置管理工具&#xff0c;旨在应对实际项目中日益增长的接口调试、开发与后期维护工作&#xff0c;这些工作负担随着项目的不断迭代而逐渐加重。接口的开发、调试、上线及下线&#xff0c;共同构成了一个接口的完整生命周期。若在项目…

作者头像 李华
网站建设 2026/9/11 2:01:58

Cat-Catch:嗅探页面全部媒体资源,M3U8 合并存 MP4

Cat-Catch&#xff1a;嗅探页面全部媒体资源&#xff0c;M3U8 合并存 MP4 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 右键另存为&#xff0c;得…

作者头像 李华