
适用读者:有 JavaScript / TypeScript 基础,想系统入门 ArkTS 与 HarmonyOS 应用开发的开发者。
本教程聚焦五个核心模块:ArkTS 语言本身 → 基础类库 → 并发机制 → 运行时 → 编译工具链,帮助你建立从"写代码"到"代码如何在设备上跑起来"的完整认知。
目录
- 第〇章 在开始之前:ArkTS 是什么,它从哪来
- 第一章 ArkTS 语言基础与类型系统(从 TypeScript 到 ArkTS)
- 第二章 ArkTS 基础类库(容器、Buffer、XML、类型工具)
- 第三章 ArkTS 并发编程(TaskPool、Worker、Sendable)
- 第四章 ArkTS 运行时(ArkCompiler Runtime)
- 第五章 ArkTS 编译工具链
- 第六章 综合实践与学习路径
第〇章 在开始之前:ArkTS 是什么,它从哪来
0.1 一句话定位
ArkTS 是 HarmonyOS(鸿蒙)官方主力应用开发语言,它在 TypeScript 生态基础上做了扩展,同时强化了静态类型检查与并发能力,并配合 ArkUI 框架提供声明式 UI 开发能力。
0.2 三者的关系:JavaScript → TypeScript → ArkTS
JavaScript (动态、弱类型,运行时才暴露错误)
↑ 超集
TypeScript (加了静态类型,编译期检查,但仍兼容宽松写法)
↑ 扩展 + 强化约束
ArkTS (强制静态类型、更严格的语义约束、声明式UI、增强并发)
关键理解:
- ArkTS 兼容 TypeScript 的语法风格 ,所以你会看到
let/const/class/interface/ 箭头函数等熟悉的写法。 - 但 ArkTS 比 TypeScript 更严格。它主动禁用了许多"灵活但危险"的特性,换取程序运行时的稳定性和性能。
- ArkTS 还 forward 扩展了 TypeScript 没有的能力:声明式 UI 装饰器、状态管理、并发任务 API。
0.3 你需要准备什么
| 工具 | 作用 |
|---|---|
| DevEco Studio | 鸿蒙官方 IDE,内置 SDK、模拟器、调试器 |
| HarmonyOS SDK | 编译运行所需的系统库 |
| 真机或模拟器 | 运行与调试(注意:并发与基础类库部分能力模拟器暂不支持) |
⚠️ 重要提示:截至当前版本,ArkTS 基础库与并发能力在模拟器上暂不支持,需要使用真机调试这部分内容。
第一章 ArkTS 语言基础与类型系统
1.1 强制静态类型
TypeScript 虽然支持类型标注,但你可以随意写 any、unknown,编译后类型信息就丢失了。ArkTS 反其道而行:
typescript
// ArkTS:必须显式标注类型,禁止隐式 any
let name: string = "HarmonyOS"; // ✅ 必须写类型
const version: number = 6.0; // ✅ 常量也要类型
// ❌ 以下在 ArkTS 中不被允许:
// let x = "hello"; // 隐式类型推导虽然可用,但推荐显式标注
// let y: any = 123; // any 类型被禁用(部分宽松模式除外)
强制静态类型的收益:由于所有类型在程序运行前就已知,编译器可以在开发期验证代码正确性,减少运行时类型检查,从而提升性能与稳定性------这正是 ArkTS "为高性能而生"的设计哲学。
1.2 与 TypeScript 的关键差异(入门必读)
这是初学者最容易踩坑的地方。ArkTS 为了性能和稳定性,主动禁用了 TS 的若干特性:
| 特性 | TypeScript | ArkTS | 说明 |
|---|---|---|---|
any / unknown |
✅ 支持 | ❌ 基本禁用 | 避免类型逃逸 |
var 关键字 |
✅ 支持 | ❌ 禁用 | 统一用 let / const |
| 对象字面量声明类型 | ✅ 支持 | ❌ 禁用 | 需先定义类/接口 |
| 运行时改变对象布局 | ✅ 允许 | ❌ 禁止 | 不能运行时增删属性 |
| 结构化类型(Structural Typing) | ✅ 支持 | ❌ 不支持 | 采用名义类型(Nominal Typing) |
in 运算符 |
✅ 支持 | ❌ 禁用 | |
生成器函数 function* |
✅ 支持 | ❌ 禁用 | 用 async/await 替代 |
| 参数解构 | ✅ 支持 | ❌ 禁用 | 需显式传参 |
| 函数内声明函数 | ✅ 支持 | ❌ 禁用 | 用 lambda 代替 |
new.target |
✅ 支持 | ❌ 禁用 | |
call/apply/bind 改 this |
✅ 支持 | ❌ 禁用 | |
一元加法 + 作用于非数字 |
✅ 允许 | ❌ 禁止 | 限制运算符语义 |
关于"结构化类型":TypeScript 里只要两个对象"长得一样"就认为类型兼容。ArkTS 不支持这种写法,要求类型必须有明确的声明(名义类型)。
关于"对象布局不可变" :ArkTS 要求对象创建后不能随便添加/删除属性。比如
obj.newProp = 1这种动态加属性的写法是不允许的。
1.3 类属性必须显式初始化
typescript
class User {
// ❌ ArkTS 不允许声明但不初始化(除非在构造函数中赋值)
// name: string;
// ✅ 正确:声明时初始化
name: string = "";
age: number = 0;
// ✅ 或者在构造函数中初始化
id: number;
constructor(id: number) {
this.id = id;
}
}
1.4 声明式 UI 装饰器(ArkTS 的标志性能力)
ArkTS 最大的扩展是声明式 UI。它用"装饰器"来赋予类和变量特殊含义:
typescript
@Entry // 标记这是一个页面入口组件
@Component // 标记这是一个可复用的 UI 组件
struct Index {
@State message: string = 'Hello World' // 状态变量:变化会驱动 UI 刷新
build() {
Column() {
Text(this.message)
.fontSize(24)
Button('点击我')
.onClick(() => {
this.message = 'Hello ArkUI' // 状态变化 → UI 自动更新
})
}
}
}
| 装饰器 | 作用 |
|---|---|
@Entry |
标识页面入口组件 |
@Component |
标识自定义 UI 组件 |
@State |
组件内部状态,变化触发 UI 重绘 |
@Prop |
父组件向子组件单向传值 |
@Link |
父子组件双向同步 |
声明式 UI 的核心思想:你描述"UI 应该长什么样"(基于当前状态),而不是写一堆"如何一步步修改 DOM"的命令。状态变了,UI 自动跟着变。
1.5 面向对象:类、接口、枚举
ArkTS 完整支持面向对象:
typescript
// 接口
interface Shape {
area(): number;
}
// 枚举
enum Color { Red, Green, Blue }
// 类 + 继承 + 实现接口
class Circle implements Shape {
radius: number = 0;
constructor(r: number) {
this.radius = r;
}
area(): number {
return 3.14159 * this.radius * this.radius;
}
}
const c: Circle = new Circle(5);
console.info(`面积 = ${c.area()}`); // 面积 = 78.53975
1.6 控制流与函数
typescript
// 条件
let score: number = 85;
if (score >= 90) {
console.info("优秀");
} else if (score >= 60) {
console.info("及格");
} else {
console.info("不及格");
}
// 循环
for (let i: number = 0; i < 5; i++) {
console.info(`第 ${i} 次`);
}
// 函数(箭头函数也支持,但函数内不能嵌套声明函数)
const add = (a: number, b: number): number => a + b;
第二章 ArkTS 基础类库
ArkTS 基础类库增强了语言的基础功能,提供高精度浮点运算、二进制 Buffer、XML 生成解析转换,以及多种容器库等能力,帮助你减少重复造轮子。
2.1 容器类库:为什么需要它
普通的 TypeScript 数组 [] 固然好用,但在高性能场景下不够"讲究"。ArkTS 容器类采用类似静态语言的方式实现,并通过约束存储位置和属性,让每种数据类型去除冗余逻辑、保证高效访问。
ArkTS 提供线性容器 和非线性容器两大类,共 14 种。
2.2 线性容器(按数组/链表实现)
线性容器实现能按顺序访问的数据结构。底层主要通过数组实现,运行时(Runtime)可通过一条字节码指令完成增、删、改、查。
| 容器 | 底层 | 特点与适用场景 |
|---|---|---|
ArrayList |
动态数组(连续内存) | 频繁读取元素时推荐;初始容量 10,每次扩容 2 倍 |
Vector |
动态数组 | 比 ArrayList 多了一套 get/set 校验接口(API 9 后不再维护,推荐用 ArrayList) |
List |
单向链表(内存可不连续) | 频繁插入/删除时推荐 |
LinkedList |
双向链表 | 需要双向遍历的场景 |
Deque |
双端队列 | 两端都可高效插入/删除 |
Queue |
队列(基于链表) | 任务调度、消息队列、缓存(先进先出) |
Stack |
栈(连续内存) | 后进先出(LIFO)场景 |
注意:
List的修改不要用list[index] = element这种方式(会导致未定义结果),应使用list.set(index, element)。
代码示例:ArrayList
typescript
import { ArrayList } from '@kit.ArkTS';
let list: ArrayList<string> = new ArrayList();
list.add("apple");
list.add("banana");
console.info(`长度: ${list.length}`); // 长度: 2
console.info(`第0个: ${list[0]}`); // 第0个: apple(支持 [] 访问)
console.info(`是否包含: ${list.has("apple")}`); // 是否包含: true
list.removeByIndex(0);
console.info(`删除后长度: ${list.length}`); // 删除后长度: 1
代码示例:Stack 与 Queue
typescript
import { Stack, Queue } from '@kit.ArkTS';
// 栈:后进先出
let stack: Stack<number> = new Stack();
stack.push(1);
stack.push(2);
console.info(`${stack.pop()}`); // 2
// 队列:先进先出
let queue: Queue<string> = new Queue();
queue.add("task1");
queue.add("task2");
console.info(`${queue.getFirst()}`); // task1
2.3 非线性容器(哈希/树实现)
非线性容器包括 HashMap、HashSet、TreeMap、TreeSet、PlainArray、LightWeightMap、LightWeightSet 等,用于键值对存储、去重、有序集合等场景。
代码示例:HashMap
typescript
import { HashMap } from '@kit.ArkTS';
let map: HashMap<string, number> = new HashMap();
map.set("Alice", 90);
map.set("Bob", 85);
console.info(`Alice 的分数: ${map.get("Alice")}`); // Alice 的分数: 90
console.info(`是否包含 Bob: ${map.hasKey("Bob")}`); // 是否包含 Bob: true
2.4 其他基础能力
ArkTS 基础库还提供:
- Buffer(二进制 Buffer):处理字节数据,常用于文件、网络、编解码。
- XML 生成/解析/转换:将对象与 XML 互转。
- 高精度浮点运算:金额、科学计算等需要精度的场景。
- 类型工具
@arkts.lang:提供ISendable等接口(详见第三章 Sendable)。
2.5 如何选择容器(经验法则)
需要按顺序、频繁随机访问?
→ ArrayList(数组) / LinkedList(频繁插入删除)
需要先进先出?
→ Queue
需要后进先出?
→ Stack
需要键值对?
→ HashMap
需要去重集合?
→ HashSet
第三章 ArkTS 并发编程
3.1 为什么需要并发
主线程(UI 线程)负责渲染界面。如果在主线程做耗时操作(大文件读写、复杂计算、图片滤镜),界面就会卡顿甚至卡死。
并发的目标:把耗时任务搬到其他线程执行,让 UI 始终保持流畅。
ArkTS 把并发分为两类:
| 类型 | 本质 | 代表技术 |
|---|---|---|
| 异步并发 | 单线程内通过事件循环"看起来同时"执行,并非真多核 | Promise / async / await |
| 多线程并发 | 真正利用多核,多个线程同时执行 | TaskPool / Worker |
简单类比:异步并发像"一个司机快速切换开两辆车";多线程并发像"两个司机各开各的车"。
3.2 Actor 模型:无锁的并发
ArkTS 的 TaskPool 和 Worker 都基于 Actor 并发模型。
核心思想:线程之间不共享内存,也不使用锁。每个线程是一个独立的"房间",房间之间只能通过"发消息"传递数据(数据会被复制过去)。
- ✅ 优点:天然无锁,杜绝死锁和竞态条件,系统更稳定。
- ⚠️ 代价:数据传递有拷贝成本,需关注传输方式(详见 3.7 Sendable)。
3.3 TaskPool:任务池(官方推荐首选)
TaskPool 是在 Worker 之上的高层封装,帮你自动管理线程池。你只需把任务丢进去,系统负责调度、负载均衡、扩缩容。
核心特性:
- 系统自动管理线程池(最大约 64 个工作线程,随负载扩缩容)。
- 支持任务优先级、任务取消、任务组(TaskGroup)。
- 同步代码执行上限约 3 分钟(异步 I/O 如网络下载、文件读写不限时)。
- 结果通过
Promise异步返回。
3.3.1 @Concurrent 装饰器
TaskPool 执行的并发函数必须用 @Concurrent 装饰,否则编译不通过。
规则:
- ✅ 只能修饰全局函数(普通函数或 async 函数)。
- ❌ 不能修饰:箭头函数、generator、类成员方法、匿名函数。
- ❌ 函数内禁止使用闭包变量(只能用入参、local 变量、import 引入的变量)。
typescript
import taskpool from '@kit.ArkTS';
// ✅ 正确:全局函数 + @Concurrent
@Concurrent
function computeSum(n: number): number {
let total: number = 0;
for (let i: number = 0; i < n; i++) {
total += i;
}
return total;
}
async function runTask(): Promise<void> {
// 1. 创建任务
let task: taskpool.Task = new taskpool.Task(computeSum, 1000000);
// 2. 执行并等待结果
let result: number = await taskpool.execute(task) as number;
console.info(`计算结果: ${result}`);
}
// 调用
runTask();
3.3.2 任务组与优先级
typescript
import taskpool from '@kit.ArkTS';
@Concurrent
function heavyWork(id: number): string {
return `任务${id}完成`;
}
async function runGroup(): Promise<void> {
let group: taskpool.TaskGroup = new taskpool.TaskGroup();
group.addTask(new taskpool.Task(heavyWork, 1));
group.addTask(new taskpool.Task(heavyWork, 2));
// 设置优先级并执行任务组
let results: Array<string> = await taskpool.execute(group, taskpool.Priority.HIGH) as Array<string>;
console.info(`结果: ${JSON.stringify(results)}`);
}
3.3.3 任务执行中向宿主线程发消息
typescript
@Concurrent
function taskWithProgress(): void {
for (let i: number = 0; i < 100; i++) {
// 向宿主线程发送进度
taskpool.Task.sendData({ progress: i });
}
}
// 宿主线程监听
let task: taskpool.Task = new taskpool.Task(taskWithProgress);
task.onReceiveData((data: object) => {
console.info(`进度: ${(data as { progress: number }).progress}`);
});
await taskpool.execute(task);
3.3.4 适用场景
- 大量或调度点分散的独立任务。
- 运行时间 ≤ 3 分钟的 CPU 密集型任务。
- 不需要常驻的"一次性"计算。
3.4 Worker:常驻后台线程
Worker 更接近传统多线程:是一个功能完备的独立线程,但需要你手动管理它的生命周期(创建、通信、销毁)。
基本用法:
typescript
// 1. 创建 Worker(指定脚本路径)
import { worker } from '@kit.ArkTS';
let w: worker.ThreadWorker = new worker.ThreadWorker("entry/ets/workers/MyWorker.ets");
// 2. 主线程接收消息
w.onmessage = (e: MessageEvents) => {
console.info(`收到结果: ${e.data}`);
};
// 3. 主线程发送消息
w.postMessage("开始计算");
// 4. 销毁(务必手动释放!)
// w.terminate();
typescript
// MyWorker.ets(Worker 线程脚本)
import { worker } from '@kit.ArkTS';
const parent: worker.ThreadWorker = worker.workerPort;
parent.onmessage = (e: MessageEvents) => {
let result: number = (e.data as number) * 2;
parent.postMessage(result); // 回传结果
};
3.4.1 适用场景
- 运行时间 超过 3 分钟的任务(如后台 1 小时的模型训练)。
- 需要常驻、有状态、持续处理消息的线程。
- 对线程生命周期需要精细控制的场景。
3.5 TaskPool vs Worker 对比
| 维度 | TaskPool | Worker |
|---|---|---|
| 抽象层级 | 高层封装(基于 Worker) | 底层线程 |
| 生命周期 | 系统自动管理 | 开发者手动管理 |
| 参数传递 | 直接传参、直接收返回值 | 需自行 postMessage 封装 |
| 优先级 | ✅ 支持 | ❌ 不支持 |
| 任务取消 | ✅ 支持 | ❌ 不支持 |
| 执行时限 | 同步代码 ≤ 3 分钟 | 不限 |
| 最大线程数 | 系统自动(约 64) | 手动(最多约 64) |
| 推荐度 | ⭐ 首选 | 特定长任务场景 |
经验法则:能用 TaskPool 就用 TaskPool;只有当任务需要长时间常驻或精细线程控制时,才用 Worker。
3.6 Sendable:跨线程共享对象(进阶重点)
默认情况下,线程间传递对象是序列化拷贝(深拷贝)------数据被复制一份传过去,两边互不影响。但这有两个痛点:
- 大数据传输慢:传 100KB 以上的数据,拷贝成本高。
- 方法会丢失:普通对象拷贝后,其携带的成员方法会丢失。
ArkTS 提出的 Sendable 机制解决了这个问题:用 @Sendable 装饰的类,跨线程传递时是引用传递(多个线程指向同一个对象),存放在共享堆(SharedHeap)中,且方法不丢失。
typescript
import { taskpool } from '@kit.ArkTS';
// 用 @Sendable 标记可共享类
@Sendable
class SharedCounter {
count: number = 0;
increment(): void {
this.count++;
}
}
@Concurrent
function workOnCounter(counter: SharedCounter): void {
counter.increment();
}
async function demo(): Promise<void> {
let counter: SharedCounter = new SharedCounter();
let task: taskpool.Task = new taskpool.Task(workOnCounter, counter);
await taskpool.execute(task);
// 由于是引用传递,counter 的修改在宿主线程可见
console.info(`count = ${counter.count}`);
}
@Sendable 的约束(很重要):
- 只能写在
.ets文件中。 - 成员属性必须是 Sendable 类型或基础类型(string / number / boolean)。
- 成员属性必须显式初始化。
- 成员函数不能使用闭包,只能用入参、this 成员或 import 变量。
- 只允许 Sendable 类继承 Sendable 类。
- 导出 Sendable 类的文件,不能导出非 Sendable 属性。
⚠️ 线程安全警告 :Sendable 对象是引用共享的,多个线程同时修改会发生数据竞争。如果多线程并发访问,需要开发者自己加同步机制(如锁)保证安全。
引用传递 vs 拷贝传递如何选择:
| 方式 | 适用场景 |
|---|---|
| 引用传递(@Sendable) | 大数据(>100KB)、需要保留方法、多线程共享同一份数据 |
| 拷贝传递(普通对象) | 数据量小、线程间需要独立副本、互不干扰 |
第四章 ArkTS 运行时(ArkCompiler Runtime)
4.1 ArkCompiler 的两大部分
ArkCompiler(方舟编译运行时)负责 ArkTS / TS / JS 的编译与运行,分为:
ArkCompiler
├── ArkTS 编译工具链 (开发侧:把高级语言编译为 .abc 字节码)
└── ArkTS 运行时 (设备侧:加载并运行 .abc 字节码,执行程序逻辑)
本章讲运行时:代码到了设备上,是怎么被执行的。
4.2 运行时由哪些模块组成
方舟 ArkTS 运行时(ARK TypeScript Runtime)是一个完整的执行环境,包含:
ArkTS 运行时
├── 对象分配器 + 垃圾回收器 (GC) ← 管内存
├── 符合 ECMAScript 规范的标准库 ← 管语言内置能力
├── ARK 字节码解释器 ← 解释执行 .abc
├── 内联缓存 (Inline Cache) ← 加速属性访问
├── 静态类型编译器 ← AOT 编译加速
└── NAPI (C/C++ 函数接口) ← 跨语言桥接
4.3 执行模式:AOT / JIT / 解释执行
ArkTS 运行时可以把字节码以多种方式执行:
| 模式 | 说明 | 特点 |
|---|---|---|
| 解释执行 | 逐条解释字节码 | 启动快,但运行慢 |
| JIT(即时编译) | 运行时把热点代码编译为机器码 | 兼顾启动与运行,但运行时有编译开销 |
| AOT(提前编译) | 打包前就把代码编译为机器码 | 运行时最快、最稳定,启动略慢 |
ArkTS 的一大优势是编译前置:相比传统 JS "运行时才编译",ArkCompiler 在开发/打包阶段就完成大量编译工作,既提前暴露错误,又提升运行时性能。
4.4 垃圾回收:HPP GC(高性能部分 GC)
GC(垃圾回收)自动管理内存,开发者不用手动 free。ArkTS 运行时采用 HPP GC(High Performance Partial Garbage Collection),特点:
分代模型:把内存按对象存活时间分区:
| 内存区 | 存放内容 |
|---|---|
| 年轻代 (Young) | 新创建、存活率低的短命对象 |
| 老年代 (Old) | 存活时间长的对象 |
| 大对象空间 (HugeObject) | 大数组等大对象 |
| 只读空间 (ReadOnly) | 字符串常量等只读数据 |
| 不可移动空间 (NonMovable) | 系统类对象 |
| 机器码空间 (MachineCode) | 编译后的机器码 |
回收算法:
- Young GC(年轻代回收):用 Copying(复制)算法------把存活对象复制到另一半区,直接回收旧半区。速度快,但回收空间有限。
- Old GC(老年代回收):用 Sweep(清扫)+ Compact(压缩)算法,回收空间多,但耗时较长。
前台/后台优化:
- 前台(应用可见):优先保证流畅,减少 GC 停顿。
- 后台(应用切到后台):触发 压缩 GC(CompressGC),同时整理年轻代和老年代,趁用户看不见时把内存彻底压缩。
对开发者的启示:理解 GC 能帮你避免"内存抖动"------比如不要在循环里疯狂创建临时大对象,会给 Young GC 造成压力。
4.5 NAPI:ArkTS 与 C/C++ 的桥梁
有些场景必须用 C/C++(游戏引擎、物理模拟、底层编解码)。HarmonyOS 提供 Node-API(NAPI),它是 ArkTS/JS 与 C/C++ 跨语言调用的接口。
典型用法:
- 系统把底层模块能力通过 NAPI 封装成 ArkTS 接口开放给应用。
- 开发者把性能敏感的核心逻辑用 C/C++ 实现,再用 ArkTS 接口调用。
4.6 内存模型:LocalHeap vs SharedHeap
回顾第三章的 Sendable,它在内存层面体现为一个关键设计:
LocalHeap (私有堆):普通 ArkTS 对象,每个线程独享
↑ 线程隔离,传递时拷贝
SharedHeap (共享堆):@Sendable 对象,多线程共享同一份
↑ 引用传递,需注意线程安全
正是这个双堆设计,让 ArkTS 既保持了 Actor 模型的线程隔离(稳定),又通过 Sendable 支持了高效的大数据共享(性能)。
第五章 ArkTS 编译工具链
5.1 工具链做了什么
编译工具链运行在开发侧(你的电脑上),核心职责是:
把 ArkTS / TS / JS 高级语言,编译为方舟字节码文件(*.abc),再打包到应用里。
设备侧的运行时(第四章)只负责执行 .abc,不需要再做重量级编译,因此启动快、运行稳。
5.2 编译流程:从 .ets 到 .abc
你的源码 (.ets / .ts)
↓
[ 1. 前端解析 ] ts2abc 组件(方舟 JS 前端工具)
↓ 类型检查、语法校验、适配 ArkTS 约束
[ 2. 生成中间表示 ]
↓
[ 3. 编译为方舟字节码 ]
↓
方舟字节码 (.abc)
↓
[ 4. 打包进 HAP/HSP ]
↓
安装到设备 → 运行时执行 .abc
其中 ts2abc 是方舟平台的关键前端组件,负责把 JavaScript/TypeScript 转换为方舟字节码。
5.3 开发期静态检查(提前暴露错误)
传统 JS 开发常见痛点是:代码写错了,要等到运行时才报错(用户已经点进去了)。
ArkTS 工具链在编译/打包阶段就做严格静态检查,把错误提前暴露在开发期。这也是为什么 ArkTS 强制静态类型、禁用 any------这些约束让编译器能"看得懂"你的代码,从而帮你查错。
传统 JS: 写代码 → 运行 → ❌ 报错(用户已受影响)
ArkTS: 写代码 → ✅ 编译期拦截错误 → 运行(更稳)
5.4 Disassembler:反汇编工具
当遇到字节码相关问题时,可以用 Disassembler(ark_disasm) 把 .abc 反编译成可读的汇编指令,用于分析底层行为。
工具随 DevEco Studio SDK 发布,位置类似:
DevEco Studio/sdk/default/openharmony/toolchains/ark_disasm.exe
命令示例:
bash
ark_disasm input.abc output.txt
5.5 自定义字节码修改
高级场景(如字节码插桩、定制优化)可以在编译期修改 .abc。在 build-profile.json5 中配置 transformLib:
json5
{
"buildOption": {
"arkOptions": {
"transformLib": "./custom_transform.so"
}
}
}
编译器会在指定时机加载这个动态库并执行其中的 Transform 方法,让你能读取并改写字节码。
5.6 DevEco Studio 与工程配置
build-profile.json5:模块级构建配置(含编译选项)。module.json5:模块配置(声明权限、Ability)。app.json5:应用全局配置。
这些文件构成了编译工具链的"输入参数",决定了代码如何被编译、打包。
第六章 综合实践与学习路径
6.1 把五块拼图拼起来
回顾一下,当我们写一段 ArkTS 代码时,背后发生的事:
① 语言层 :你用 ArkTS(强制类型 + 装饰器)写 UI 与逻辑
↓
② 基础类库:用 ArrayList/HashMap 等容器高效组织数据
↓
③ 并发层 :用 @Concurrent + TaskPool 把耗时计算丢到子线程,
用 @Sendable 在多线程间高效共享数据
↓
④ 编译工具链:ts2abc 把代码编译为 .abc,开发期静态检查提前查错
↓
⑤ 运行时 :设备上的 ArkCompiler 运行时解释/执行 .abc,
GC 自动管理内存,NAPI 桥接底层能力
6.2 动手练习建议
- 基础 :写一个带
@State的计数器页面(掌握声明式 UI + 状态驱动)。 - 容器 :用
ArrayList/HashMap实现一个学生成绩管理系统。 - 并发 :用
@Concurrent+ TaskPool 计算 1 到 100 万的累加,并观察主线程不卡顿。 - Sendable:对比"普通对象跨线程(拷贝)"与"@Sendable 对象(引用)"的差异。
- 深入 :用 Disassembler 反编译你的
.abc,看看字节码长什么样。
6.3 学习资源方向
- 官方文档:华为 HarmonyOS 开发者联盟(ArkTS 指南、API 参考)。
- 动手优先:ArkTS 的约束(禁
any、禁闭包等)只有在写代码时才会真正理解。 - 真机调试:并发与基础类库的进阶能力必须用真机验证。
附录:常见误区速查
| 误区 | 正解 |
|---|---|
| "ArkTS 就是 TypeScript" | 是 TS 的超集 + 强化约束 + UI/并发扩展 |
| "用 TaskPool 随便写个函数就行" | 必须用 @Concurrent,且不能闭包、不能是类方法 |
| "多线程就能直接共享变量" | ArkTS 默认拷贝传递;要共享得用 @Sendable |
| "Worker 比 TaskPool 高级所以更好" | TaskPool 是首选;Worker 仅用于长任务/精细控制 |
| "GC 会自动管内存,随便 new" | 仍要避免内存抖动,尤其在循环里 |
| "模拟器能测一切" | 基础库与并发在模拟器暂不支持,需真机 |
本教程为原创入门学习材料,基于华为官方文档与公开技术资料整理编写,旨在帮助初学者系统建立 ArkTS 知识体系。