第十三章:端云一体化开发
本章配套代码:
code/Chapter13(云同步 Demo,模拟云端交互) 前置要求:已完成网络请求与数据存储章节 说明:端云一体化需要华为账号 + AGC 平台,本章以模拟 Demo + 概念讲解为主,提供完整实战路径
13.1 学习目标
- 理解端云一体化开发模式与传统开发的区别
- 认识 Cloud Foundation Kit(云开发服务)
- 了解云函数、云数据库、云存储三大云服务
- 掌握端云一体化工程的创建与目录结构
- 通过模拟 Demo 理解端云交互流程
13.2 端云一体化开发概述
端云一体化开发是 HarmonyOS 基于 DevEco Studio,以 Cloud Foundation Kit(云开发服务) 为底座,实现端侧(应用)与云侧(服务)在同一工具内协同开发的模式。
┌─────────────────────────────────────────────────────────┐
│ 端云一体化开发 │
│ │
│ DevEco Studio(唯一开发工具) │
│ ┌────────────────┐ ┌────────────────┐ │
│ │ 端开发工程 │ │ 云开发工程 │ │
│ │ (Application) │ │ (CloudProgram) │ │
│ │ ArkTS/ArkUI │ │ Node.js │ │
│ └───────┬────────┘ └───────┬────────┘ │
│ │ 同一工程,协同开发 │ │
│ └──────────┬─────────────┘ │
│ ▼ │
│ Cloud Foundation Kit(云底座) │
│ ┌───────────┬────────────┬──────────────┐ │
│ │ 云函数 │ 云数据库 │ 云存储 │ │
│ └───────────┴────────────┴──────────────┘ │
│ ▼ │
│ AGC 云端(AppGallery Connect) │
└─────────────────────────────────────────────────────────┘
与传统开发模式对比:
| 对比项 | 传统开发 | 端云一体化 |
|---|---|---|
| 开发工具 | 端云各自工具 | 仅 DevEco Studio |
| 服务器 | 自建,成本高 | 免运维,自动弹性伸缩 |
| 开发人员 | 前后端多人 | 端侧开发者即可 |
| 部署 | 复杂流程 | 一键部署到 AGC |
| 收费 | 按服务器 | Serverless 按量计费 |
13.3 Cloud Foundation Kit 三大云服务
| 云服务 | 功能 | 类比 |
|---|---|---|
| 云函数 | 运行业务逻辑,无需服务器 | 后端接口 |
| 云数据库 | 结构化数据存取 | 数据库 |
| 云存储 | 文件/图片上传下载 | 对象存储 |
13.3.1 云函数(CloudFunction)
在云端执行代码,实现业务逻辑:
// 云侧代码(Node.js)
exports.handler = async function (event, context, callback) {
const result = {
code: 0,
data: {
id: generateUUID(), // 生成全局唯一 id
message: '海内存知己,天涯若比邻'
}
}
callback(null, result)
}
// 端侧调用(ArkTS)
import { cloud } from '@kit.CloudFoundationKit'
const res = await cloud.function().call('id-generator', {})
console.log(res.result) // 云端返回值
💡 端侧通过
cloud.function().call(函数名, 参数)调用云端函数,整个过程无需自己搭建服务器。
13.3.2 云数据库(CloudDB)
云端结构化数据存储,端侧通过对象类型 CRUD:
// 端侧新增数据
const res = await cloud.database().insert('Post', {
title: '第一条云数据',
content: '白云千载空悠悠',
createdAt: Date.now()
})
// 端侧查询数据
const posts = await cloud.database().query('Post').limit(10).get()
💡 CloudDB 采用 存储区 / 对象类型 / 数据条目 三级结构,支持在 AGC 或本地定义数据模型。
13.3.3 云存储(CloudStorage)
文件与图片上传下载:
// 端侧上传文件
const res = await cloud.storage().upload({
src: 'file:///data/.../avatar.png',
dstName: 'images/avatar.png'
})
// res.downloadUrl 为可访问的链接
13.4 创建端云一体化工程
13.4.1 前提条件
- 已实名认证的华为开发者账号(注册地在中国境内)
- 已登录 DevEco Studio
- 账号无欠费
13.4.2 创建步骤
- 欢迎页 Create Project
- 选择 Application > [CloudDev] Empty Ability(通用云开发模板)
- 配置工程信息:
| 参数 | 说明 |
|---|---|
| Bundle name | 需与 AGC 同包名应用一致 |
| Compatible SDK | API 12(5.0.0)及以上 |
| Enable CloudDev | 默认启用,不可更改 |
| Device type | 仅支持手机 |
- 点击 Next,关联 AGC 云开发资源
- 签署云开发协议,点击 Finish
- DevEco 自动同步:端侧
ohpm install、云侧npm install - 自动开通云函数/云数据库/云存储服务
⚠️ 云开发目前仅支持中国站点,请确保 AGC 项目启用了中国数据处理位置。
13.4.3 工程目录结构
端云一体化工程包含端开发工程(Application) 与云开发工程(CloudProgram):
MyCloudApp/
├── Application/ # 端开发工程
│ ├── cloud_objects/ # 云对象端侧调用接口
│ └── src/main/ets/
│ ├── entryability/
│ └── pages/
│ ├── CloudDatabase.ets # 云数据库页面
│ ├── CloudFunction.ets # 云函数页面
│ ├── CloudStorage.ets # 云存储页面
│ └── Index.ets # 主入口导航
├── CloudProgram/ # 云开发工程
│ ├── clouddb/ # 云数据库
│ │ ├── dataentry/ # 数据条目(.json)
│ │ ├── objecttype/ # 对象类型定义
│ │ └── db-config.json
│ └── cloudfunctions/ # 云函数
│ └── id-generator/ # 云函数示例
│ ├── index.js
│ └── package.json
├── build-profile.json5
└── oh-package.json5
13.5 端云交互流程
┌──────────┐ 调用 ┌───────────┐
│ 端侧 │ ───────────────────> │ 云侧 │
│ ArkTS │ cloud.function() │ Node.js │
│ │ <─────────────────── │ │
│ UI展示 │ 返回数据 │ 业务逻辑 │
└──────────┘ └───────────┘
│ │
▼ ▼
用户操作 云数据库/云存储
典型流程(以"新增笔记"为例):
- 端侧用户填写笔记内容
- 端侧调用云函数
createNote,传递参数 - 云函数校验数据,写入云数据库
- 云函数返回结果
- 端侧解析结果,刷新 UI
13.6 综合示例:云同步 Demo
对应 code/Chapter13 的 Index.ets,模拟云端交互流程(无需真实 AGC 环境即可运行):
@ObservedV2
class SyncItem {
@Trace key: string
@Trace value: string
constructor(key: string, value: string) {
this.key = key
this.value = value
}
}
@Entry
@ComponentV2
struct Index {
@Local syncKey: string = ''
@Local syncValue: string = ''
@Local syncData: SyncItem[] = []
@Local isLoading: boolean = false
@Local status: string = '未同步'
private syncCounter: number = 0
async syncToCloud() {
if (!this.syncKey || !this.syncValue) {
this.status = '请输入 Key 和 Value'
return
}
this.isLoading = true
this.status = '同步中...'
// 模拟云端同步(真实场景为调用 cloud.database() 等云服务)
await new Promise(resolve => setTimeout(resolve, 1000))
this.syncCounter++
this.syncData = [
...this.syncData,
new SyncItem(this.syncKey, `${this.syncValue} (云端 #${this.syncCounter})`)
]
this.syncKey = ''
this.syncValue = ''
this.status = `同步成功 (${new Date().toLocaleTimeString()})`
this.isLoading = false
}
build() {
Column({ space: 16 }) {
Text('Chapter 13: 端云一体化')
.fontSize(24)
.fontWeight(FontWeight.Bold)
Text('Cloud Sync 云同步演示')
.fontSize(14)
.fontColor('#666666')
Row({ space: 8 }) {
TextInput({ placeholder: 'Key', text: this.syncKey })
.layoutWeight(1)
.onChange((v: string) => { this.syncKey = v })
TextInput({ placeholder: 'Value', text: this.syncValue })
.layoutWeight(1)
.onChange((v: string) => { this.syncValue = v })
}
.width('100%')
Button('同步到云端')
.width('100%')
.onClick(() => this.syncToCloud())
.enabled(!this.isLoading)
if (this.isLoading) {
LoadingProgress()
.width(40)
.height(40)
}
Row() {
Text('状态: ').fontSize(14)
Text(this.status)
.fontSize(14)
.fontColor(this.status.includes('成功') ? '#00A86B' : '#007DFF')
}
Divider()
Text(`云端数据 (${this.syncData.length} 条)`)
.fontSize(14)
.fontWeight(FontWeight.Bold)
if (this.syncData.length === 0) {
Text('暂无云端数据')
.fontSize(14)
.fontColor('#999999')
} else {
List({ space: 8 }) {
ForEach(this.syncData, (item: SyncItem) => {
ListItem() {
Row() {
Text(item.key)
.fontSize(14)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
Text(item.value)
.fontSize(14)
.fontColor('#666666')
.layoutWeight(2)
}
.width('100%')
.padding(12)
.backgroundColor(Color.White)
.borderRadius(8)
}
})
}
.layoutWeight(1)
}
}
.width('100%')
.height('100%')
.padding(16)
.backgroundColor('#f5f5f5')
}
}
运行效果:
- 输入 Key/Value,点击"同步到云端"
- 模拟网络延迟,显示"同步中..." + LoadingProgress
- 成功后状态变绿,数据追加到"云端数据"列表
- 理解端云交互的异步 + 状态反馈模式
运行效果截图:



🔧 升级为真实端云:按照 15.4 创建 CloudDev 工程,将
syncToCloud中的模拟代码替换为cloud.database().insert(...)/cloud.function().call(...)即可。
13.7 云函数开发要点
// 云函数代码(Node.js)
exports.handler = async function (event, context, callback) {
try {
// 1. 解析入参
const { key } = event.body || {}
// 2. 业务逻辑(读写数据库、调用第三方等)
// ...
// 3. 返回统一结构
callback(null, { code: 0, message: 'ok', data: { /* ... */ } })
} catch (e) {
callback(null, { code: -1, message: e.message })
}
}
端侧调用与错误处理:
import { cloud } from '@kit.CloudFoundationKit'
import { BusinessError } from '@kit.BasicServicesKit'
async function callFunction<T>(funcName: string, param: object): Promise<T> {
try {
const res = await cloud.function().call(funcName, param)
const result = JSON.parse(JSON.stringify(res.result)) as { code: number, data: T }
if (result.code === 0) {
return result.data
}
throw new Error('云函数返回错误')
} catch (e) {
throw new Error((e as BusinessError).message)
}
}
13.8 云数据库开发要点
对象类型(模型)定义(clouddb/objecttype):
{
"objectTypeName": "Post",
"permissions": { "read": "authed", "write": "owner" },
"fields": [
{ "fieldName": "id", "fieldType": "string" },
{ "fieldName": "title", "fieldType": "string" },
{ "fieldName": "content", "fieldType": "string" },
{ "fieldName": "createdAt", "fieldType": "long" }
]
}
端侧 CRUD:
// 新增
await cloud.database().insert('Post', { id: 'p1', title: '标题', content: '内容', createdAt: Date.now() })
// 查询
const list = await cloud.database().query('Post').limit(20).get()
// 更新
await cloud.database().update('Post', { title: '新标题' }, { id: 'p1' })
// 删除
await cloud.database().delete('Post', { id: 'p1' })
13.9 端云一体化最佳实践
| 建议 | 说明 |
|---|---|
| 数据模型先行 | 先在云侧定义对象类型,再生成端侧接口 |
| 云函数瘦身 | 复杂逻辑放云端,端侧只做展示 |
| 统一返回结构 | { code, message, data } 三字段 |
| 错误处理 | 端侧捕获 BusinessError 展示友好提示 |
| 安全策略 | 云数据库权限(read/write)按需设置 |
| 本地缓存 | 断网场景用 Preferences/KVStore 兜底 |
13.10 常见问题
Q:云开发服务怎么开通? 创建 CloudDev 工程时自动开通。失败可在 DevEco 的 CloudDev 面板或 AGC 控制台手动开通。
Q: 创建工程提示"账户欠费"? 云存储服务需要账户可用余额,充值后在 AGC 手动开通。
Q:端侧调用云函数报错? 检查函数是否已部署到云端、函数名是否正确、参数格式是否匹配。
Q:模拟 Demo 和真实云开发的差距?
模拟 Demo 用于理解交互流程与状态管理;真实开发需 AGC 环境,核心是替换模拟代码为 cloud.xxx 调用。
13.11 本章小结
| 知识点 | 说明 |
|---|---|
| 端云一体化 | 同一工具开发端云两侧 |
| Cloud Foundation Kit | 云开发服务底座 |
| 云函数 | 云端业务逻辑 |
| 云数据库 | 云端结构化存储 |
| 云存储 | 文件图片存储 |
| CloudDev 工程 | Application + CloudProgram |
13.12 课后练习
- 在 AGC 创建应用并开通云开发服务
- 创建 CloudDev 工程,运行官方模板三个云服务 Demo
- 定义
Todo对象类型,实现待办云端增删改查 - 编写云函数实现数据校验并调用测试
- 将
Chapter13模拟 Demo 升级为真实端云应用