资讯动态

鸿蒙实战:ArkTS+ArkUI仿写三大应用,打通后台接口与多媒体

发布时间:2026/9/28 12:46:50 来源:尧图企业网站定制
学鸿蒙开发的朋友大都知道鸿蒙HarmonyOS开源以后市面上的教程是不缺的但真正能让你照着练、练完还有成就感的项目很少。我当初给自己定了个小目标用知乎日报、爱影家、爱音乐这三个大家每天都在用的App当靶子仿写一套鸿蒙应用同时自己搭一个后台接口把数据打通。这个过程中ArkTS语法、ArkUI声明式UI、网络请求、列表渲染、多媒体播放、RESTful接口设计这些硬核技能全都会过一遍而且每个阶段都有肉眼可见的成果。下面这些内容不是我背书得来的是我从写第一行ArkTS开始一点一点试出来的。涉及具体步骤、代码片段、接口设计思路都是为了让你能快速把整个链路跑通。适合刚开始接触鸿蒙的应用开发者也适合Android/iOS或前端转鸿蒙的朋友。那些文档里没写清楚的坑比如模拟器连不上本地接口、请求报错2300056、多媒体组件播放没声音等我会单独拿出来讲。如果你正在准备鸿蒙岗位的面试这套项目做完之后列表缓存、多媒体释放、证书校验这些细节全都是能拿出来聊的实战经验。1. 项目概述为什么会选“三件套”加一套后台接口1.1 “三件套”背后覆盖的三类应用形态先说为什么挑知乎日报、爱影家、爱音乐这三个名字。很多人学鸿蒙会觉得“没项目可做”其实不是因为鸿蒙生态缺素材而是大家都陷在例子里出不来——官方示例多是单一的组件demo看完只能会画按钮连一个能用的界面都搭不出来。我把这三个App当成三个典型的“业务模板”知乎日报代表的是内容聚合类应用首页要信息流、分类列表、下拉刷新、详情页跳转还有最麻烦的Web富文本页面。爱影家代表的是视频媒体类应用要分类Tab、视频卡片、播放器页面、播放历史接口里要管好视频地址和封面图这些媒体字段。爱音乐代表的是音频媒体类应用音乐列表、播放控制条、歌词同步、进度条拖动难度集中在状态管理和本地持久化上。这三个场景合起来基本覆盖了一个商业App里最常见的90%功能。你把它们写完再去写电商、资讯、工具类应用思路是通用的。这里也顺便回应一个很多人问的问题OpenHarmony和鸿蒙正式版到底什么关系简单说开源鸿蒙是底座面向生态和开发者商业版鸿蒙是用户手机里跑的那个系统。做应用开发时你用到的核心API、ArkUI能力、网络与多媒体接口在这两边是同一套体系。理解这一点就够了没必要纠结更细的版本线。1.2 后台接口在整条链路里的位置刚开始学鸿蒙很多人把精力全砸在前端页面上结果页面画完了发现没有数据只能写死值一刷新就露馅。要让App“活”起来后台接口和前端页面是两条腿缺一条都跑不起来。但注意一个度学习阶段不要试图去“借用”某些真实App的后台接口。一方面有版权和使用条款问题另一方面很多接口有加密签名你花一周也未必能调通。我用的方案是自建Mock接口先用一个极轻量的后端把真实接口的形态模拟出来等前端逻辑全部跑通再换成正规的云端API。这个思路放到真实项目中也是一样的后端接口没出时前端可以先对着Mock接口开发后端出了再无缝切换。自建Mock接口还有个隐形好处你被迫去思考“接口该长什么样”。很多前端写了一两年都没认真考虑过数据从哪来、字段名是谁定的。自己做一回后端你在定义JSON结构时会更能体会前端解析的难处这也是全栈意识的开端。1.3 一条完整的闯关路线整个学习过程我拆成了四关环境关装好DevEco Studio跑通一个ArkTS页面。数据关自己写一个后台接口把JSON数据源准备好。页面关先做知乎日报的信息流再做爱影家的视频列表最后做爱音乐的播放控制。调优关把模拟器调试、真机调试、抓包排障、打包签名都过一遍。这样安排有个好处每一关都是上一关的结果。你写页面时已经有接口能出数据修改反馈是即时可见的不会出现“写完了但不知道对不对”的悬空感。2. 开发环境准备与ArkTS基础2.1 DevEco Studio环境搭建开发鸿蒙应用第一步是装DevEco Studio官方IDE基于IntelliJ IDEA定制。去鸿蒙开发者官网下载对应平台版本即可。装的时候有几个细节安装路径尽量不要带中文SDK和IDE都放纯英文路径后续编译会省很多麻烦。SDK组件在首次创建项目时会提示下载选最新稳定版即可。API版本不建议追新稳定版API 9或10足够跑通本项目。首次启动后会让你创建工程选Empty Ability模板包名建议用com.example.xxx的格式后面签名和真机调试都跟它有关。创建完项目你会看到跟Android Studio类似的目录结构但核心代码在entry/src/main/ets目录下。需要特别注意entry/src/main/module.json5这个文件模块配置、权限声明都在这里改后面接网络请求时必须在这里加上INTERNET权限。这里多说一句鸿蒙生态现在不只是手机还有平板、车机、PC方向。PC版鸿蒙的讨论很热但作为应用开发者目前还是先专注手机端应用能力。把一套ArkUI掌握扎实以后多端适配只是布局和交互细节的调整不会推倒重学。2.2 ArkTS与ArkUI快速上手很多Android开发者第一次打开ArkTS代码会觉得不像Java也不像Kotlin更像TypeScript。ArkTS本质上是TS的超集加了更严格的类型限制和状态管理能力。你要先接受几个核心概念装饰器Entry、Component、State、Prop、Link。我的理解是装饰器的作用有点像是在组件上贴标签告诉系统哪些变量是响应式数据、哪些页面是入口页。哪个变量想驱动UI刷新就给它加一个State否则就普通变量省性能。UI组件Text、Button、Column、Row、List、Scroll跟Flutter的组件思想类似。布局方式上Column是纵向排列Row是横向排列背后是CSS flexbox那一套。状态管理ArkUI的状态管理是整个框架的精髓。父组件传值给子组件用Prop比较复杂的外卖对象传递用ObjectLink或Observed跨页面共享数据可以配合AppStorage或本地Preferences。新手阶段先用好State和Prop就够了。我刚开始总想用命令式的思路“设置某个文本框的值”后来发现ArkUI里不能这么干只能改状态让UI自己响应变化。这个思维转换很关键——你一旦适应了写页面会非常快。写几个页面之后你甚至会觉得这种“先声明界面结构再只管数据”的写法比传统Android布局更贴近现代前端开发习惯。2.3 没有真机也能调试预览器与模拟器的组合打法很多人问我手头没有鸿蒙手机怎么调试其实现在工具链已经非常成熟了。DevEco Studio自带三个调试手段Previewer预览器不跑模拟器也能看到大部分UI布局适合页面开发阶段快速迭代。它的优点是启动快改完代码点一下就去刷新我平时写列表页、详情页时基本都用它。Local Emulator本地模拟器在IDE里下载一个系统镜像后就能跑适合验证网络请求、多媒体播放这些预览器模拟不了的能力。Remote Emulator云真机华为提供的云端设备部分开发阶段可以用但网络依赖比较强。我的习惯是写UI开Previewer测流程开Local Emulator做真机适配时再连实体设备。没有手机并不耽误学鸿蒙至少这个项目我大部分时间都在模拟器上跑的。有一个点要提前说模拟器上跑网络请求时有个经典陷阱模拟器里的“localhost”是模拟器自己不是你电脑。这个我们下面讲接口时细说这里先记住这个结论。3. 后台接口设计与Mock服务搭建3.1 先画一张接口清单后台接口设计的第一步不是写代码而是把“前端需要什么数据”列出来。我做的三个App各需要一组接口统一的返回格式是{ code: 0, msg: ok, data: {} }code为0是成功非0是各种业务错误码。这样前端只要判断code就能知道请求是否成功不用去解析底层各种异常。接口清单大概长这样模块接口路径方法说明知乎日报/api/news/latestGET获取最新新闻列表知乎日报/api/news/detail?idxxxGET获取新闻详情HTML爱影家/api/videos/list?categoryxxxpage1GET按分类获取视频列表爱影家/api/videos/detail?idxxxGET视频详情爱音乐/api/songs/listGET获取歌曲列表爱音乐/api/songs/detail?idxxxGET获取歌曲、歌词、封面分页参数我用page和pageSize返回里带上total字段前端据此判断还有没有下一页。这种设计是行业里最常见的学会了换公司也是一样的套路。3.2 用json-server一分钟搭起本地Mock服务这里我选了json-server属于Node.js生态里最轻量的Mock工具一条命令就能把JSON文件变成RESTful API。前提是你电脑上有Node环境。先全局安装npm install -g json-server然后创建一个db.json里面塞上新闻、视频、歌曲的数据。数据源里的图片地址和媒体地址可以直接用一些公共的占位服务如picsum.photos这类生成保证前端能加载到内容。启动服务json-server --watch db.json --port 3000 --host 0.0.0.0注意后面的--host 0.0.0.0这一条很多人会漏掉。如果你的模拟器或手机要在局域网里访问这台电脑必须监听所有网卡地址否则只有电脑本机能访问模拟器里会一直请求失败。还有一个坑json-server默认监听localhost如果App跑在模拟器里模拟器里的localhost指向模拟器自己不是你的电脑。解决办法很简单启动时绑定0.0.0.0然后App里填电脑的局域网IP比如192.168.1.105不要填localhost。3.3 鸿蒙侧网络请求封装与权限配置鸿蒙里发网络请求用的是系统提供的http模块。首先要确认module.json5里加了网络权限{ module: { requestPermissions: [ { name: ohos.permission.INTERNET } ] } }不加这一条请求会直接失败而且报错信息不够直观很容易让人绕弯路。然后我封装了一个HttpUtils类核心逻辑是统一请求和异常处理import http from ohos.net.http; export class HttpUtils { static async getT(url: string): PromiseT { const httpRequest http.createHttp(); const response await httpRequest.request(url, { method: http.RequestMethod.GET, connectTimeout: 30000, readTimeout: 30000, expectDataType: http.HttpDataType.STRING }); if (response.responseCode 200) { return JSON.parse(response.result as string) as T; } throw new Error(HTTP ${response.responseCode}); } }为什么用泛型 因为新闻接口返回的data是个数组视频接口返回的data是另一个结构用泛型让调用方自己声明类型类型安全更好。后续把http换成axios或者升级为最新网络库只需要改这一个文件。3.4 抓包调试看清接口的每一个返回前端联调阶段我很推荐养成抓包的习惯。抓包并不是为了做什么灰色操作纯粹是开发调试的常规手段——看看自己的App请求了哪个地址、传了什么参数、返回了什么东西。我用的是Charles和DevEco自带的网络日志工具两个可以配合。鸿蒙模拟器抓包时要把模拟器的代理指向电脑的IP和Charles的端口同时安装Charles的根证书。这一步在设置里有向导跟着点就行。真机调试更简单只要手机和电脑同一局域网把WiFi代理设成电脑IP启动抓包即可。调试完一定要关掉代理不然手机上网会变慢。另外有一点特别重要如果你在抓包时改了系统证书这个调试环境是不安全的绝对不能带到生产环境去。生产环境的所有请求必须走正规的HTTPS证书这是上线前的底线。4. 仿“知乎日报”列表、详情与缓存4.1 首页信息流ArkUI列表组件实战知乎日报的首页核心是信息流结构就是“顶部图片轮播 多条新闻卡片”。用ArkUI的List组件来做列表配合ForEach渲染数据。写代码时要注意ForEach的第三个参数——键值生成器必须返回一个唯一id。我一开始偷懒没写结果列表更新时页面出现了“复用错乱”比如第一条数据突然变成了第十条。用item.id.toString()作为键值就能解决。基本页面结构Entry Component struct NewsListPage { State newsList: ArrayNewsItem []; async aboutToAppear() { this.newsList await HttpUtils.getApiResponseArrayNewsItem(this.baseUrl /api/news/latest); } build() { List({ space: 12 }) { ForEach(this.newsList, (item: NewsItem) { ListItem() { NewsCard({ item: item }) .onClick(() { router.pushUrl({ url: pages/NewsDetailPage, params: { id: item.id } }); }); } }, (item: NewsItem) item.id.toString()); } .padding(12) .width(100%) .layoutWeight(1) } }这里aboutToAppear生命周期钩子对应的是页面即将展示类似Android的onCreate。await一下拿到数据后再赋值给State列表就会自动刷新。整个流程写下来你会发现ArkUI的响应式设计真的很省事不用手动调adapter.notifyDataSetChanged。4.2 详情页与WebView资讯类App的详情页通常不是原生页面而是渲染HTML富文本。知乎日报的详情更是如此。鸿蒙里加载网页内容用Web组件它既支持加载远程URL也支持加载本地HTML字符串。从列表页跳过来时用router.getParams()拿到新闻idconst params router.getParams() as Recordstring, number; const newsId params.id;然后再请求详情接口把返回的HTML塞进Web组件Web({ src: htmlContent, controller: this.webviewController }) .width(100%) .height(100%)这里有个细节如果后端返回的是相对路径引用的图片比如在Web组件里加载HTML字符串时需要设置baseUrl否则图片全挂。我一开始图片全灰后来才发现是这个原因。4.3 下拉刷新、分页加载与缓存信息流还有一个高频需求下拉刷新和上拉加载。鸿蒙里的Refresh组件自带刷新能力只要在onRefresh回调里重新请求第一页数据即可。分页加载我用的是监听滚动位置到末尾再加载下一页。List组件的onReachEnd事件正好能判断滚动到底部拿到新的page参数去请求把结果追加到数组尾部。缓存策略我用了Preferences也就是轻量级键值对数据库。用户刷完列表后把最近的若干条数据存到本地下次冷启动先进缓存再拉新数据。代码如下import preferences from ohos.data.preferences; async function saveCache(key: string, data: string) { const store await preferences.getPreferences(getContext(), cache); await store.put(key, data); await store.flush(); }Preferences在鸿蒙里不能直接存复杂对象存JSON字符串最稳妥。读出来的时候再JSON.parse回来。做这个缓存功能时我建议把接口的返回结构保持稳定否则旧缓存和新数据格式对不上页面会崩。5. 仿“爱影家”与“爱音乐”多媒体应用实战5.1 用Video组件实现“爱影家”播放页视频类App的核心差异就在播放器。ArkUI内置的Video组件封装了播放器能力支持自动播放、控制条、全屏等基础用法非常简单Entry Component struct VideoPlayerPage { State videoUrl: string ; controller: VideoController new VideoController(); build() { Column() { Video({ src: this.videoUrl, controller: this.controller }) .width(100%) .height(240) .controls(true) .autoPlay(true) } } }但真正开发你会遇到几个更实际的问题。第一视频地址要用HTTP还是HTTPS取决于后端服务。本地调试时http没问题上线前尽量上HTTPS。第二视频源指向本地局域网时偶尔加载特别慢这不是播放器问题多半是后端没做流媒体支持直接返回了整个MP4。做个小测试文件、用支持Range请求的静态文件服务器体验会好很多。播放历史这块我在5.3小节一起讲。5.2 用AVPlayer实现“爱音乐”播放控制音乐App的难点不在列表而在播放控制。ArkUI里最常用的音视频播放能力在ohos.multimedia.media这个API里新版是AVPlayer支持音频和视频统一播放。核心流程是创建AVPlayer实例 - 设置媒体源 - 准备 - 播放。import media from ohos.multimedia.media; async function playSong(url: string) { const avPlayer await media.createAVPlayer(); avPlayer.url url; await avPlayer.prepare(); await avPlayer.play(); }音频播放不需要申请麦克风权限只要网络权限就行。控制播放进度时AVPlayer有on(timeUpdate)回调拿到当前播放时间后去刷新进度条。进度条拖动则用seek方法。歌词同步的原理也简单把LRC歌词解析成“时间标签 - 歌词文本”的数组在timeUpdate里根据当前时间找到对应索引行UI高亮该行即可。这里我踩过最大的坑是创建AVPlayer之后没有及时销毁。音乐页切走再切回来新页面又创建了一个AVPlayer旧实例还在后台占资源重复播放几百毫秒声音串了。正确做法是在页面销毁钩子里调用release()把播放器实例清理掉。5.3 本地存储与播放历史播放历史是一个很考验基本功的小功能。不管是视频还是音乐用户希望“上次看到/听到哪下次接着来”。我用的方案是借助Preferences存一个播放记录数组数据结构大概是这样[ { id: video_123, type: video, title: 某部电影, position: 120000, duration: 5400000, updateTime: 1719999999 } ]播放页在onDisappear时把当前进度写回存储列表页在onPageShow时重新读取并展示“续播”入口。注意一个性能细节不要每次拖动进度条就写一次存储播放的seek事件频率很高会造成IO压力。我的做法是只在播放暂停、停止、页面隐藏三个时机写入其它时间的进度直接放内存变量。6. 鸿蒙开发高频报错排查实录6.1 常见错误码速查表把网络请求相关的报错码整理成表格遇到就直接查错误码典型场景排查方向2300056HTTPS请求证书校验失败确认证书是否有效、是否配置了网络安全策略、调试期证书是否可信2300001网络不可达或超时检查IP、端口、防火墙、设备网络2300018URL格式不合法检查地址是否缺少协议头、含非法字符2300046请求Body不是合法JSON检查POST请求的Content-Type和body格式2300056是很多人搜不到的冷门错误它往往出现在“Android/iOS请求都正常唯独鸿蒙请求挂了”的场景。鸿蒙对网络安全的要求更严格默认会对证书做严格校验。如果后端是自签证书或者一些奇怪的中间代理环境就会触发。开发期可以临时调整调试策略但上线必须走正规CA证书。6.2 联网请求相关的三个典型案例案例一模拟器能打开首页但无法请求本机的json-server。问题基本出在localhost。模拟器里的localhost指向它自己必须换成电脑的局域网IP同时后端启动要带--host 0.0.0.0。案例二真机请求电脑接口偶发失败。排查三步手机和电脑连同一个WiFi确认防火墙没有拦截3000端口确认后端加日志看有没有收到请求。我自己碰到过一次是手机连的WiFi和电脑不是同一个网段中间隔了路由器的AP隔离请求根本到不了电脑换到同一个路由器下就正常了。案例三json-server返回中文乱码。多半是Content-Type没带charsetutf-8。json-server通常没问题但如果你用自己写的Node/Spring Boot接口一定要在响应头里明确字符集。6.3 打包与签名踩坑提示开发阶段DevEco Studio可以开启自动签名IDE会帮你生成本地证书真机安装和hap打包都没问题。但要注意自动签名的证书有效期通常只有一年过期后重新签名即可。发布应用则需要注册并配置发布证书签名和调试证书不是一个体系不能混用。在鸿蒙开发者社区里也有人会问能不能用第三方工具扫描hap包的安全问题类似移动应用安全扫描那一套。官方提供了应用签名校验和安全检测工具装完构建出的hap包也可以放到检测平台看权限和漏洞报告。初学者不用过度焦虑安全扫描但要有这个意识线上的包和调试包不能是同一个签名权限申请也要按最小化原则来。还有个小坑很多人在打包hap时选了错误的module或者build variant导致打出来的包安装不了。其实打包前先在构建菜单里看一眼当前目标是debug还是release签名配置是否正确。这些检查习惯建议一开始就培养能省很多无谓的报错排查时间。7. 我的学习路径与个人体会走完整个流程之后我的体会特别简单学鸿蒙一定不要隔着屏幕看视频一定要上手写。哪怕是从复制、修改一个页面开始至少要让手指亲自敲一遍代码。不踩过几个坑你永远不会理解为什么List要写键值生成器为什么网络请求要封装成一个类为什么多媒体对象要记得释放。我个人还会再加一步把这三个App项目同步开源到代码托管平台。写给别人看的过程会逼着你去理解自己的代码为什么这么写。如果你是刚开始学也可以先找身边人评审你的代码你会发现很多自己没意识到的粗糙习惯。下一步我还打算往这套项目里加两样东西一是用户注册登录用本地数据库模拟账号体系二是推送通知让新闻类应用真正具备实时性。你会发现当第一层链路跑通之后加新功能只是在你搭好的骨架上添砖加瓦。希望这篇记录能给你一条少走弯路的参考路线。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑