# 鸿蒙 6 新华字典实战:从零到一用 ArkTS 开发原生鸿蒙应用

## 一、背景

HarmonyOS 6.0 发布以来,鸿蒙原生应用生态快速发展。作为一名开发者,我决定用 ArkTS 和 ArkUI 开发一款实用的新华字典应用,通过对接 ALAPI 新华字典接口,实现汉字查询、拼音、部首、笔画、释义等完整功能。

本文将从项目初始化、UI 搭建、网络请求、设备调试到最终部署,完整记录整个开发过程。

---

## 二、开发环境

| 工具 | 版本 |
|------|------|
| OpenHarmony SDK | 23(API 11) |
| Hvigor | 6.24.2 |
| HDC | 3.2.0d |
| 目标设备 | HarmonyOS 6.1.0(ALN-AL00) |
| 开发语言 | ArkTS(ETS) |
| UI 框架 | ArkUI |

开发在 macOS 上进行,使用命令行工具链而非 IDE,这样可以更清晰地理解鸿蒙应用的构建流程。

---

## 三、项目初始化

### 3.1 创建项目

使用 DevEco Studio 创建 Empty Ability 模板项目,项目名为 `MyApplication`,包名为 `com.nutpi.myapplication`。

创建后的项目结构:

```
MyApplication/
├── AppScope/                     # 应用级配置
├── entry/                        # 主模块
│   ├── src/main/ets/
│   │   ├── entryability/         # Ability 入口
│   │   └── pages/                # 页面
│   ├── src/main/resources/       # 资源文件
│   └── build-profile.json5       # 模块构建配置
├── build-profile.json5           # 应用构建配置
├── hvigorfile.ts                 # 构建脚本
└── oh-package.json5              # 包管理
```

### 3.2 SDK 版本适配

查看 `build-profile.json5`,发现默认配置了 SDK 6.1.1(24):

```json5
{
  "products": [{
    "targetSdkVersion": "6.1.1(24)",
    "compatibleSdkVersion": "6.1.1(24)",
  }]
}
```

连接设备后发现设备运行的是 HarmonyOS **6.1.0.117**(型号 ALN-AL00),对应的 SDK 版本为 23。需要降级适配:

```json5
{
  "products": [{
    "targetSdkVersion": "6.1.0(23)",
    "compatibleSdkVersion": "6.1.0(23)",
  }]
}
```

> **踩坑经验**:如果 targetSdkVersion 高于设备 SDK 版本,hdc install 会报错 `install failed due to older sdk version in the device`。必须确保 targetSdk 与设备匹配。

---

## 四、数据模型设计

根据 ALAPI 接口的实际返回格式定义数据模型。

### 4.1 接口信息

- **地址**:`POST https://v3.alapi.cn/api/word`
- **请求头**:`Content-Type: application/json`
- **参数**:`token`(接口凭证)、`word`(要查询的汉字)

### 4.2 实际返回结构

```json
{
  "success": true,
  "code": 200,
  "message": "success",
  "data": [{
    "word": "好",
    "old_word": "好",
    "strokes": 6,
    "pinyin": "hǎo",
    "radical": "女",
    "explanation": "好〈形〉 (会意。从女,从子。本义美,貌美)...",
    "more": "好 hao 部首 女 部首笔画 03 总笔画 06..."
  }],
  "time": 1780569751,
  "usage": 0
}
```

### 4.3 模型定义

```typescript
export interface WordResponse {
  success: boolean;
  code: number;
  message: string;
  data: WordItemData[];
  time: number;
  usage: number;
}

export interface WordItemData {
  word: string;
  old_word: string;
  strokes: number;
  pinyin: string;
  radical: string;
  explanation: string;
  more: string;
}
```

> **注意**:`data` 是数组而非单个对象,且字段名为 `radical`(单数)而非 `radicals`。组词和成语信息全部整合在 `more` 字段的纯文本中,没有独立的结构化字段。

---

## 五、网络请求模块

### 5.1 使用 @kit.NetworkKit

HarmonyOS 提供 `@kit.NetworkKit` 中的 `http` 模块用于网络请求:

```typescript
import { http } from '@kit.NetworkKit';
import { WordResponse } from '../model/WordData';
import { API_TOKEN } from './ApiConfig';

const API_URL = 'https://v3.alapi.cn/api/word';

export function queryWord(word: string): Promise<WordResponse> {
  return new Promise((resolve, reject) => {
    const httpRequest = http.createHttp();

    httpRequest.request(
      API_URL,
      {
        method: http.RequestMethod.POST,
        header: {
          'Content-Type': 'application/json',
        },
        extraData: JSON.stringify({
          token: API_TOKEN,
          word: word,
        }),
        connectTimeout: 15000,
        readTimeout: 15000,
      },
      (err, data) => {
        if (err) {
          httpRequest.destroy();
          reject(new Error(`网络请求失败: ${err.message}`));
          return;
        }
        // 解析响应...
      }
    );
  });
}
```

### 5.2 关键点

1. **extraData 需要序列化**:`extraData` 传入 JSON 对象时需要手动 `JSON.stringify()`,不能直接传对象字面量。
2. **回调 VS Promise**:`http.request()` 的第三个参数是回调函数,我们在回调内手动封装为 Promise。
3. **资源释放**:每次请求完成后必须调用 `httpRequest.destroy()` 释放连接。

---

## 六、API Token 安全管理

### 6.1 问题

API Token 是敏感信息,不能硬编码在代码中提交到远程仓库。

### 6.2 解决方案

创建独立的配置文件,加入 `.gitignore`:

```typescript
// ApiConfig.ets - 真实配置(被 gitignore 忽略)
export const API_TOKEN: string = '你的token';
```

```typescript
// ApiConfigTemplate.ets - 模板(可提交)
export const API_TOKEN: string = '请填入你的API token';
```

`.gitignore` 中添加:

```
**/ApiConfig.ets
```

开发者克隆项目后:

```bash
cp ApiConfigTemplate.ets ApiConfig.ets
# 编辑 ApiConfig.ets 填入真实 token
```

---

## 七、UI 实现

### 7.1 页面结构

应用采用单页面设计,包含三个状态视图:

```
┌──────────────────────┐
│    新华字典(标题)     │
├──────────────────────┤
│ [🔍 请输入汉字...] [🔍]│  ← 搜索栏
├──────────────────────┤
│                      │
│  ● 初始状态:引导提示    │
│  ● 加载中:Loading     │
│  ● 错误:错误信息       │
│  ● 结果:信息卡片       │
│                      │
└──────────────────────┘
```

### 7.2 搜索栏实现

```typescript
Row() {
  TextInput({
    placeholder: '请输入要查询的汉字...',
    text: this.searchWord
  })
    .layoutWeight(1)
    .fontSize(16)
    .height(48)
    .backgroundColor('#f0f0f5')
    .borderRadius(24)
    .onChange((value) => { this.searchWord = value.trim(); })
    .onSubmit(() => { this.doSearch(); })

  Button() { Text('🔍').fontSize(20) }
    .width(48).height(48).borderRadius(24)
    .backgroundColor('#4a6cf7')
    .onClick(() => { this.doSearch(); })
}
```

### 7.3 结果卡片实现

使用 `@Builder` 封装可复用的 UI 组件:

```typescript
@Builder
buildWordHeader() {
  Row() {
    Text(this.wordData!.word)       // 大号汉字
      .fontSize(56).fontWeight(FontWeight.Bold)

    Column() {
      Text(this.wordData!.pinyin)   // 拼音
      Row() {                       // 部首 + 笔画
        Text('部首: ' + this.wordData!.radical)
        Text('笔画: ' + this.wordData!.strokes + '画')
      }
    }
  }
}

@Builder
buildSectionCard(title: string, content: string) {
  Column() {
    Text(title).fontSize(17).fontWeight(FontWeight.Bold)
    Text(content).fontSize(14).lineHeight(22)
  }
  // 圆角卡片样式...
}
```

### 7.4 卡片样式设计

每张结果卡片使用白色背景、圆角 + 阴影,形成 Material Design 风格的卡片布局:

```typescript
.backgroundColor('#ffffff')
.borderRadius(16)
.padding(18)
.margin({ left: 16, right: 16, top: 8, bottom: 8 })
.shadow({
  radius: 8,
  color: 'rgba(0,0,0,0.06)',
  offsetY: 2
})
```

### 7.5 关于 @Builder 的注意点

ArkTS 中自定义 UI 组件需要使用 `@Builder` 注解:

```typescript
@Builder  // ← 必须加注解
buildWordHeader() { ... }
```

在 `build()` 中调用时需要用 `this.` 前缀:

```typescript
this.buildWordHeader()  // ✅ 正确
buildWordHeader()       // ❌ 编译错误:Cannot find name
```

---

## 八、网络权限配置

HarmonyOS 应用需要显式声明网络权限。在 `module.json5` 中添加:

```json5
{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      }
    ]
  }
}
```

不添加此权限将导致网络请求失败。

---

## 九、构建与部署

### 9.1 构建 HAP

使用 hvigorw 命令行构建:

```bash
hvigorw assembleHap --mode module -p product=default -p buildMode=debug
```

构建产物在 `entry/build/default/outputs/default/` 目录下:
- `entry-default-signed.hap`(已签名的安装包)
- `entry-default-unsigned.hap`(未签名包)

### 9.2 安装与启动

```bash
# 查看已连接的设备
hdc list targets

# 安装 HAP
hdc install entry/build/default/outputs/default/entry-default-signed.hap

# 启动应用
hdc shell "aa start -a EntryAbility -b com.nutpi.myapplication"
```

### 9.3 查看运行时日志

```bash
hdc shell "hilog -x -L error"
```

---

## 十、遇到的坑与解决方案

### 10.1 SDK 版本不匹配

**现象**:`hdc install` 报错 `install failed due to older sdk version in the device`

**解决**:检查设备 SDK 版本,将 `build-profile.json5` 中的 targetSdkVersion 降级为设备兼容的版本。

### 10.2 extraData 格式问题

**现象**:请求成功但服务端返回异常

**解决**:`extraData` 需要 `JSON.stringify()` 序列化,同时 `Content-Type` 必须设为 `application/json`。

### 10.3 设备锁屏无法启动

**现象**:`aa start` 报错 `The device screen is locked during the application launch`

**解决**:先唤醒屏幕:`hdc shell "power-shell wakeup"`,再启动应用。或者在设备设置中关闭开发者模式。

### 10.4 组件找不到的错误

**现象**:编译报错 `UI component 'Row' cannot be used in this place`

**解决**:自定义 UI 方法需添加 `@Builder` 注解,并在 `build()` 中用 `this.` 调用。

### 10.5 HTTP 模块类型定义

**现象**:`http.RequestMethod.POST` 编译报错

**解决**:确认 SDK 版本对应的 API。SDK 23 使用 `@kit.NetworkKit`,使用 `http.RequestMethod.POST` 符合规范。

---

## 十一、项目心得

1. **命令行效率**:使用 hvigorw + hdc 命令行工具链,比 IDE 更可控,适合 CI/CD 集成。

2. **ArkUI 的声明式开发体验**:ArkUI 借鉴了声明式 UI 的思想,与 SwiftUI、Jetpack Compose 类似,学习曲线对前端/移动开发者来说相对平缓。

3. **鸿蒙 SDK 兼容性**:不同版本的 SDK 差异较大,开发前务必确认设备 API 版本。

4. **API Token 安全管理**:敏感信息必须通过配置文件管理,加入 `.gitignore`,提供模板供其他开发者参考。

---

## 十二、总结

本文完整记录了使用 ArkTS + ArkUI 开发鸿蒙新华字典应用的全过程,从环境搭建、接口对接、UI 构建到设备部署。整个项目代码量约 300 行,涵盖了一个完整鸿蒙应用的核心技术点。

虽然鸿蒙生态仍在快速演进,但 ArkTS 的开发体验已经相当成熟。随着 HarmonyOS NEXT 的推进,原生鸿蒙应用开发将成为越来越重要的技能方向。

---

## 项目地址

本文所有代码已开源:[https://gitcode.com/jianguoxu/myapplication](https://gitcode.com/jianguoxu/myapplication)
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐