在这里插入图片描述
在这里插入图片描述

本文基于 HarmonyOS NEXT API 24(SDK 6.1.1),完整记录了一款"旅游规划助手"AI 应用的开发全过程。不同于传统的问答工具,本应用通过拟人化角色设定、趣味交互细节和丰富的动效反馈,让 AI 对话"活"了起来。涵盖 Stage 模型、ArkTS 声明式 UI、SSE 流式解析、状态管理、定时轮播、自定义 Builder 组件等核心技术点。


一、从工具到伙伴:AI 应用的"温度"设计

1.1 为什么需要"有温度"的 AI 交互

在移动应用日益同质化的今天,用户对 AI 助手的需求已经从"能回答问题"升级为"愿意和它聊天"。一个冷冰冰的对话框很难留住用户,而一个有性格、有情绪、会开玩笑的 AI 伙伴却能让人产生情感连接。

本项目将 AI 设定为 “旅行小太阳 🌞”——一个热情、贴心、还有点幽默的旅行规划师。她不是机械地输出攻略,而是像朋友一样聊天、推荐、给建议。

1.2 项目技术选型

技术层 选型 版本/说明
操作系统 HarmonyOS NEXT API 24 (SDK 6.1.1)
开发语言 ArkTS Huawei 声明式语言
UI 框架 ArkUI 声明式 UI + @State 响应式
应用模型 Stage 模型 推荐标准模型
网络请求 @kit.NetworkKit 原生 HTTP 库
AI 模型 DeepSeek-V3 GitCode API 接入
通信协议 SSE Server-Sent Events 流式推送
构建工具 hvigor 6.24.2 版本

1.3 项目目录结构

Demo022/
├── AppScope/
│   ├── app.json5                      # 应用配置(bundleName、版本等)
│   └── resources/base/element/
│       └── string.json                # "旅游规划助手" 应用名
├── entry/
│   ├── build-profile.json5            # 模块构建配置
│   ├── oh-package.json5               # 依赖声明
│   └── src/main/
│       ├── ets/
│       │   ├── AIChatService.ets      # 核心网络层(SSE + 流式解析)
│       │   ├── entryability/
│       │   │   └── EntryAbility.ets   # Ability 生命周期
│       │   └── pages/
│       │       └── Index.ets          # 主界面(507行,含全部交互逻辑)
│       ├── module.json5               # 模块注册
│       └── resources/
├── hvigor/                            # 构建配置
└── build-profile.json5                # 全局构建(targetSdk: 24)

二、Stage 模型与 Ability 生命周期

2.1 Stage 模型简介

HarmonyOS NEXT 的 Stage 模型将应用逻辑拆分为 Ability 和 AbilityStage 两层。每个 Ability 代表一个独立的功能入口,拥有完整的生命周期方法:

onCreate → onWindowStageCreate → onForeground → 运行中
    ↑                                           ↓
    └──── onBackground ← onWindowStageDestroy ← onDestroy

2.2 EntryAbility 实现

import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';

const DOMAIN = 0x0000;

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    // 跟随系统深浅色模式
    try {
      this.context.getApplicationContext()
        .setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
    } catch (err) {
      hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode: %{public}s', JSON.stringify(err));
    }
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        hilog.error(DOMAIN, 'testTag', 'Failed: %{public}s', JSON.stringify(err));
        return;
      }
    });
  }
}

关键点

  • setColorMode(COLOR_MODE_NOT_SET) 让应用跟随系统自动切换深色/浅色模式
  • loadContent('pages/Index', callback) 加载主页面
  • 使用 hilog 进行分级日志输出,DOMAIN 参数用于日志分类

三、AI 网络层深度解析 — AIChatService

3.1 类型系统设计

良好的类型定义是 ArkTS 代码质量的基石:

// 消息结构
export interface ChatMessage {
  role: string;      // "system" | "user" | "assistant"
  content: string;
}

// 请求体
export interface ChatCompletionRequest {
  model: string;
  messages: ChatMessage[];
  stream: boolean;
  max_tokens: number;
  temperature: number;
  top_p: number;
  frequency_penalty: number;
  thinking_budget: number;
}

// 回调接口 — 解耦网络层与 UI 层
export interface AICallbacks {
  onData: (text: string) => void;   // 流式 token 到达
  onDone: () => void;               // 响应结束
  onError: (errMsg: string) => void; // 错误处理
}

设计亮点:通过 AICallbacks 接口将网络层与 UI 层完全解耦,网络层无需关心 UI 如何渲染,UI 层只需实现三个回调方法。

3.2 提示词工程 — 塑造"旅行小太阳"人格

系统提示词(System Prompt)是决定 AI 回复质量和风格的灵魂。本项目设计了基于角色扮演的提示词:

const SYSTEM_PROMPT: string =
  '你是一位充满热情的旅行规划专家,叫做"旅行小太阳",擅长为用户打造独一无二的旅行体验。' +
  '你熟知全球热门和小众目的地,对不同季节、不同人群的旅行需求有独到见解。\n\n' +
  '以下是你的5大超能力:\n' +
  '1. 🌟 梦想解码:通过几个简单问题就能精准捕捉用户的旅行幻想\n' +
  '2. 🗺️ 路线魔法:设计每日行程时像讲故事一样,有起承转合、有惊喜彩蛋\n' +
  '3. 💰 预算炼金术:不管预算多少都能变出最物超所值的方案\n' +
  '4. 🎯 隐藏宝藏雷达:推荐本地人私藏的秘境和小众体验\n' +
  '5. 📋 贴心小棉袄:主动提醒天气、穿搭、签证等\n\n' +
  '回复风格:用热情活泼的语气,适当加入😊✈️🏖️🎒等表情符号';

提示词工程技巧

  • 角色命名:“旅行小太阳”——有温度、有记忆点的名字
  • 超能力框架:5 个能力用 🌟🗺️💰🎯📋 符号化,易于 AI 理解和记忆
  • 风格约束:“像和朋友聊天一样轻松有趣”,控制回复语气
  • 结构建议:“小标题、emoji 和换行”,控制排版风格

3.3 SSE 流式协议与解析

SSE (Server-Sent Events) 是 AI API 的标准流式传输协议。服务器将数据以 data: {...}\n\n 格式逐行推送:

data: {"choices":[{"delta":{"content":"你"}}]}

data: {"choices":[{"delta":{"content":"好"}]}]

data: [DONE]
逐行解析器
function parseSSEDataLine(line: string): string | null {
  const jsonStr = line.slice(5).trim();  // 去掉 "data:" 前缀
  if (!jsonStr) return null;

  try {
    const parsed = JSON.parse(jsonStr) as Record<string, Object>;
    const choices = parsed.choices as Object[];
    if (choices && choices.length > 0) {
      const choice = choices[0] as Record<string, Object>;
      // 兼容 delta(流式)和 message(非流式)
      const delta = choice.delta as Record<string, Object>;
      if (delta) return delta.content as string;
      const message = choice.message as Record<string, Object>;
      if (message) return message.content as string;
    }
  } catch (_) { /* 跳过非法行 */ }
  return null;
}

关键细节

  • line.slice(5) 精确移除 “data:” 前缀
  • 同时兼容 delta(流式逐 token)和 message(非流式全量)两种格式
  • 异常捕获保证单行解析失败不影响后续处理
三层回退容错

考虑到 HarmonyOS 不同版本对 SSE 事件的支持差异,实现了 3 层容错:

优先级 机制 触发条件 体验
1(首选) dataReceive 事件 框架支持 SSE 逐事件推送 打字机效果 ✅
2(次选) 完整响应按 SSE 解析 dataReceive 未触发 一次显示全文
3(兜底) 完整响应按 JSON 解析 服务端返回非流式格式 一次显示全文
// 非流式回退机制
if (!receivedAnyData && resp.result) {
  const bodyStr = typeof resp.result === 'string'
    ? resp.result
    : arrayBufferToString(resp.result as ArrayBuffer);

  // 优先解析 SSE 格式
  const sseContent = parseFullSSEBody(bodyStr);
  if (sseContent) {
    callbacks.onData(sseContent);
  } else {
    // 回退到 JSON 格式
    const jsonContent = parseNonStreamingBody(bodyStr);
    if (jsonContent) {
      callbacks.onData(jsonContent);
    } else {
      callbacks.onError(`无法解析响应`);
      return;
    }
  }
}

3.4 请求取消与资源管理

let httpRequestTask: http.HttpRequest | null = null;

export function cancelAI(): void {
  if (httpRequestTask) {
    httpRequestTask.destroy();  // 释放网络资源
    httpRequestTask = null;
  }
}

每次发起新请求前自动取消上一次请求,避免多请求并发导致 UI 状态错乱。


四、有趣的 UI 设计 — Index.ets 全解析

本章是核心亮点,将详细介绍如何让 AI 对话界面"有趣"起来。

4.1 整体布局架构

Stack (根容器,支持背景叠加)
├── Column (背景渐变层 — 浅天蓝→爱丽丝蓝→暖米白)
└── Column (前景内容层)
    ├── Column (顶部标题栏)
    │   ├── Row (✈️ 小太阳旅行规划 🌞 — 标题文字)
    │   └── Text (轮播旅行Tips)
    ├── Scroll (消息列表)
    │   └── Column
    │       ├── ForEach → MessageBubble(item) [消息气泡]
    │       ├── if → AIBubble() [流式内容] / LoadingIndicator() [加载]
    │       └── if → QuickTagRow() [快捷标签,仅对话开始时显示]
    └── Row (底部输入区)
        ├── TextInput (圆角输入框)
        ├── Blank (间距)
        └── Button (✈️ 发送/取消)

4.2 渐变背景与色彩体系

// 背景渐变
Column()
  .linearGradient({
    direction: GradientDirection.Bottom,
    colors: [
      ['#E8F4FD', 0.0],   // 浅天蓝
      ['#F0F8FF', 0.5],   // 爱丽丝蓝
      ['#FFF8F0', 1.0],   // 暖米白
    ],
  })

// 顶部栏渐变(天空蓝 → 日落橙)
.linearGradient({
  direction: GradientDirection.Right,
  colors: [
    ['#4A90D9', 0.0],     // 天空蓝
    ['#5BA0E8', 0.5],     // 亮蓝
    ['#FF8C5A', 1.0],     // 日落橙
  ],
})

配色心理学:蓝色系传递"天空、旅行、自由"的感觉,暖橙色渐变代表"日落、温暖、温度",整体营造出轻松愉快的旅行氛围。

4.3 轮播旅行 Tips — setInterval 定时器

const FUN_TIPS: string[] = [
  '💡 淡季出行不仅省钱,游玩体验翻倍哦!',
  '💡 当地菜市场是体验地道文化的最佳地点!',
  '💡 周二下午买机票通常最便宜 ✈️',
  '💡 用一瓶水就能拍出绝美倒影照 📸',
  '💡 旅行中迷路往往是最难忘的经历 😄',
];

@State tipIndex: number = 0;
private tipTimer: number = -1;

aboutToAppear(): void {
  this.startTipRotation();
}

aboutToDisappear(): void {
  this.stopTipRotation();
}

startTipRotation(): void {
  this.tipTimer = setInterval(() => {
    this.tipIndex = (this.tipIndex + 1) % FUN_TIPS.length;
  }, 5000);  // 每 5 秒切换一条
}

stopTipRotation(): void {
  if (this.tipTimer !== -1) {
    clearInterval(this.tipTimer);
    this.tipTimer = -1;
  }
}

生命周期管理要点

  • aboutToAppear 中启动定时器(页面可见时)
  • aboutToDisappear 中停止定时器(页面不可见时)
  • 防止页面隐藏后定时器仍在执行,浪费性能和导致状态异常

4.4 快捷提问标签系统 — 降低用户门槛

6 个旅行主题标签,点击即问,无需输入:

const QUICK_TAGS: QuickTag[] = [
  { icon: '🏖️', text: '周末去哪玩' },
  { icon: '🎓', text: '毕业旅行' },
  { icon: '👨‍👩‍👧‍👦', text: '亲子游推荐' },
  { icon: '💰', text: '穷游攻略' },
  { icon: '🌸', text: '赏花好去处' },
  { icon: '🏔️', text: '小众秘境' },
];
标签网格布局

ArkUI 的 ForEach 不支持直接二维渲染,通过 chunkArray 将 6 个标签分为 2 行 × 3 列:

@Builder QuickTagRow() {
  Column() {
    Text('💬 试试问我这些:')
      .fontSize(13).fontColor('#888888')
      .margin({ bottom: 8 })

    ForEach(this.chunkArray(QUICK_TAGS, 3), (row: QuickTag[]) => {
      Row({ space: 8 }) {
        ForEach(row, (tag: QuickTag) => {
          Button() {
            Text(`${tag.icon} ${tag.text}`)
              .fontSize(13).fontColor('#4A90D9')
          }
          .height(36).borderRadius(18)
          .backgroundColor('#E8F2FF')
          .border({ width: 1, color: '#B8D4F0' })
          .layoutWeight(1)
          .onClick(() => this.handleQuickTag(tag.text))
        })
      }
      .width('100%').margin({ bottom: 6 })
    })
  }
}

// 数组分块工具函数
chunkArray(arr: QuickTag[], size: number): QuickTag[][] {
  const result: QuickTag[][] = [];
  for (let i = 0; i < arr.length; i += size) {
    result.push(arr.slice(i, i + size));
  }
  return result;
}

设计决策

  • 标签只在 messages.length <= 2 时显示(即未开始或刚发送一条消息),避免干扰后续对话
  • 点击后 showQuickTags = false 隐藏标签,为用户输入腾出空间
  • 蓝色边框(#B8D4F0)+ 浅蓝背景(#E8F2FF),与整体旅行主题一致

4.5 消息气泡设计

用户消息 — 暖橙色右对齐
if (item.role === 'user') {
  Blank()  // 占位,右对齐
  Column() {
    Text(item.content).fontSize(15).lineHeight(22)
  }
  .padding({ left: 16, right: 16, top: 12, bottom: 12 })
  .backgroundColor('#FFE0B2')  // 暖橙色
  .borderRadius({ topLeft: 18, topRight: 4, bottomLeft: 18, bottomRight: 18 })
  .constraintSize({ maxWidth: '75%' })
  .shadow({ radius: 2, color: '#15000000', offsetY: 1 })
}
AI 消息 — 白色左对齐 + 头像
Column() {
  Row() {
    Text('🌞').fontSize(20)       // 小太阳头像
    Text(' 旅行小太阳').fontSize(13).fontColor('#4A90D9')
  }
  .margin({ bottom: 6 })

  Text(item.content).fontSize(15).lineHeight(24)
}
.padding({ left: 16, right: 16, top: 12, bottom: 14 })
.backgroundColor('#FFFFFF')
.borderRadius({ topLeft: 4, topRight: 18, bottomLeft: 18, bottomRight: 18 })
.constraintSize({ maxWidth: '82%' })
.shadow({ radius: 3, color: '#15000000', offsetY: 1 })

气泡造型技巧

  • 非对称 borderRadius:靠近对方的一侧小圆角(4px),营造"气泡尾"效果
  • 左下角圆形(用户) / 左上角圆形(AI),视觉上形成对话感的对仗
  • shadow 阴影增加立体层次感
  • constraintSize({ maxWidth }) 限制气泡最大宽度,避免文字过长

4.6 趣味加载动画

10 条随机加载语
const LOADING_TIPS: string[] = [
  '正在翻看旅行攻略书... 📚',
  '给小行李箱装知识... 🧳',
  '飞机正在起飞中... ✈️',
  '向本地人打听隐藏景点... 🗣️',
  '用地图画出一条有趣的路线... 🗺️',
  '查询当地天气和穿搭建议... 🌤️',
  '搜索地道美食清单... 🍜',
  '计算最佳出行时间... ⏰',
  '偷偷加了一些小众彩蛋... 🎁',
  '给行程配上BGM... 🎵',
];
加载动画组件
@Builder LoadingIndicator() {
  Row() {
    Column() {
      Row() {
        Text('🌞').fontSize(20)
        Text(' 旅行小太阳').fontSize(13).fontColor('#4A90D9')
      }
      .margin({ bottom: 8 })

      Row() {
        Text('✈️') .fontSize(16).rotate({ angle: -15 }).margin({ right: 4 })
        LoadingProgress().width(20).height(20).color('#4A90D9')
        Text(LOADING_TIPS[this.loadingTipIndex]).fontSize(13).fontColor('#666666')
      }
    }
    .padding(...).backgroundColor('#FFFFFF')
    .borderRadius({ topLeft: 4, topRight: 18, ... })
    .shadow(...)
    Blank()
  }
}

有趣设计点

  • 小飞机 ✈️ 添加 rotate({ angle: -15 }) 倾斜效果,模拟飞行姿态
  • LoadingProgress 是 HarmonyOS 原生的旋转加载组件
  • 每次调用 AI 前执行 getRandomLoadingTip() 随机选取一条,每次加载都有新鲜感

4.7 发送按钮状态机

发送按钮有 3 种状态,通过 @State 驱动:

状态 条件 外观 行为
空闲 + 有输入 inputText.trim() && !isLoading 蓝色背景 + ✈️ 点击发送
空闲 + 无输入 !inputText.trim() 灰色背景 + ✈️ 禁用
加载中 isLoading 蓝色背景 + LoadingProgress 点击取消请求
Button() {
  if (this.isLoading) {
    LoadingProgress().width(22).height(22).color('#FFFFFF')
  } else {
    Text('✈️').fontSize(20)
  }
}
.backgroundColor(
  this.inputText.trim() && !this.isLoading ? '#4A90D9' : '#CCCCCC'
)
.enabled(!!this.inputText.trim() && !this.isLoading)

4.8 发送消息完整流程

sendMessage(): void {
  const text = this.inputText.trim();
  if (!text || this.isLoading) return;

  // 1. 隐藏快捷标签
  this.showQuickTags = false;

  // 2. 添加用户消息并清空输入
  this.messages.push({ role: 'user', content: text });
  this.inputText = '';

  // 3. 滚动到底部
  setTimeout(() => this.scroller.scrollEdge(Edge.Bottom), 100);

  // 4. 切换加载状态
  this.isLoading = true;
  this.currentAIResponse = '';
  this.getRandomLoadingTip();

  // 5. 构建历史消息(不含 system prompt)
  const chatHistory: ChatMessage[] = this.messages.map<ChatMessage>((m) => ({
    role: m.role,
    content: m.content,
  }));

  // 6. 调用 AI
  queryAI({
    onData: (text: string) => {
      this.currentAIResponse += text;
      setTimeout(() => this.scroller.scrollEdge(Edge.Bottom), 50);
    },
    onDone: () => {
      if (this.currentAIResponse) {
        this.messages.push({ role: 'assistant', content: this.currentAIResponse });
      }
      this.isLoading = false;
      this.currentAIResponse = '';
      setTimeout(() => this.scroller.scrollEdge(Edge.Bottom), 100);
    },
    onError: (errMsg: string) => {
      this.messages.push({
        role: 'assistant',
        content: '🌧️ 哎呀,旅行遇到了一点小状况:' + errMsg + '\n\n再试一次吧~'
      });
      this.isLoading = false;
      this.currentAIResponse = '';
    },
  }, chatHistory);
}

关键设计决策

  • map<ChatMessage>() 显式泛型,满足 ArkTS 严格类型检查
  • setTimeout 延迟 50-100ms 再滚屏,等待 DOM 更新完成
  • onDone 中将 currentAIResponse 作为完整消息推入列表,而非逐 token 推入
  • 错误友好提示:“🌧️ 旅行遇到小状况” 保持角色一致性

五、ArkTS 严格模式与避坑指南

5.1 常见编译错误及解决方案

错误 1:arkts-no-untyped-obj-literals

对象字面量必须对应显式声明的接口

// ❌ 错误
this.messages.map((m) => ({ role: m.role, content: m.content }));

// ✅ 正确
this.messages.map<ChatMessage>((m) => ({
  role: m.role, content: m.content,
}));
错误 2:maxWidthColumnAttribute 上不存在
// ❌ 错误
Column().maxWidth('75%')

// ✅ 正确
Column().constraintSize({ maxWidth: '75%' })

constraintSize 是 ArkUI 的通用尺寸约束属性,支持 minWidthmaxWidthminHeightmaxHeight

错误 3:on 方法已弃用
// 当前版本可用但产生警告
httpRequest.on('dataReceive', callback);

5.2 编译输出解读

hvigorw assembleHap --mode module -p module=entry@default -p product=default

成功输出示例:

BUILD SUCCESSFUL in 2s 379ms

WARN: ArkTS:WARN - 'on' has been deprecated.    # 可忽略,兼容旧API
WARN: ArkTS:WARN - need INTERNET permission      # 提示性警告
WARN: Will skip sign 'hos_hap'                   # 开发模式无签名

六、性能优化与编码实践

6.1 状态管理最佳实践

  1. 最小化 @State:只有影响 UI 渲染的变量才标记为 @State,避免不必要重绘
  2. 条件渲染优先:使用 if 而非 Visibility 控制组件显隐,减少组件树复杂度
  3. ForEach key:第三个参数 (item, index) => index.toString() 提供稳定 key,帮助框架复用节点

6.2 网络优化

  1. 连接取消:每次新请求前销毁旧连接,防止内存泄漏
  2. 超时控制connectTimeout: 30sreadTimeout: 120s
  3. 数据解码优化arrayBufferToString 使用 String.fromCharCode 逐字节转换,避免大字符串拼接性能问题

6.3 内存管理

  1. 定时器生命周期aboutToAppear 启动,aboutToDisappear 停止
  2. 流式缓冲区清空onDone / onError 中将 currentAIResponse 置空
  3. HTTP 资源释放httpRequest.destroy() 及时释放网络资源

6.4 ArkTS 编码规范

规范 说明 示例
显式类型 所有变量、参数标注类型 const text: string = ''
接口先行 先定义接口再实现 interface AICallbacks { ... }
模块化 网络层与 UI 层分离 AIChatService ↔ Index.ets
常量提取 魔法数字/字符串提取为常量 LOADING_TIPS, FUN_TIPS

七、构建与部署

7.1 开发构建

hvigorw assembleHap --mode module -p module=entry@default -p product=default

7.2 真机安装

hdc install entry/build/default/outputs/default/entry-default-unsigned.hap

7.3 常见问题排查

问题 原因 解决方案
on 弃用警告 API 24 中 on() 标记弃用 可忽略,向下兼容
INTERNET 权限 未声明网络权限 module.json5 添加 ohos.permission.INTERNET
签名警告 未配置签名证书 开发模式可忽略
SSE 不触发 部分 HarmonyOS 版本兼容性 非流式回退机制自动处理

八、总结与扩展方向

8.1 项目特色总结

  1. 拟人化 AI 角色:“旅行小太阳 🌞” 让 AI 不再冷冰冰,5 大超能力设定让回复更有趣
  2. 三层 SSE 容错:适配不同 HarmonyOS 版本的网络行为差异
  3. 快捷标签降低门槛:6 个旅行主题标签,一键提问
  4. 轮播 Tips 增加粘性:5 秒切换实用旅行小贴士,让用户有意外收获
  5. 趣味加载语:10 条随机加载语 + 小飞机 ✈️ 倾斜动效,等待不再无聊
  6. 暖色调视觉体系:天空蓝 → 日落橙渐变 + 暖橙气泡,传递"温暖旅行"的品牌感知

8.2 可扩展方向

  • 多轮上下文优化:当前历史消息完整传递,可针对性优化上下文窗口
  • 图片/位置分享:利用 HarmonyOS 分布式能力分享景点图片和地图定位
  • 离线知识库:集成本地旅行攻略,无网络也能提供基础建议
  • 语音交互:集成 @kit.VoiceKit,支持语音输入旅行需求
  • 多设备协同:手机规划 → 手表查看 → 平板展示,全场景覆盖

8.3 写在最后

本项目的核心启示是:AI 应用的竞争力不在技术有多复杂,而在细节有多用心。从"旅行小太阳"的角色设定,到轮播 Tips 的趣味选择,再到每次加载时不同的小彩蛋——正是这些看似不起眼的细节,让一个普通的问答工具变成了一个有温度、有性格的旅行伙伴。

HarmonyOS NEXT 的 ArkTS 和 ArkUI 提供了现代化声明式开发体验,希望本文能为 HarmonyOS 开发者带来实用的参考和启发。


本文基于 HarmonyOS NEXT API 24(SDK 6.1.1)编写,于 2026 年 6 月完成。部分 API 可能随版本更新而变化,请以华为官方文档为准。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐