一、熟悉概念
鸿蒙开发相关的一些概念,打开官网,看到的就是这几个套件

二、简单介绍
* DevEco Studio:类似 Android Studio.
* ArkTS:ArkTS 是鸿蒙生态的应用开发语言。
全称 TypeScript (简称TS)基本语法风格的基础上,对 TS 的动态类型特性施加更严格的约束,引入静态类型。 提供了声明式 UI、状态管理等相应的能力,可以更简洁、更自然的方式开发高性能应用。
* ArkUI
ArkUI 是一套构建分布式应用界面的声明式 UI 开发框架。它使用极简的 UI 信息语法、丰富的 UI 组件、以及实时界面预览工具,帮助您提升 HarmonyOS 应用界面开发效率30%。您只需使用一套 ArkTS API,就能在多个 HarmonyOS 设备上提供生动而流畅的用户界面体验。
可以理解为用 TS 实现的一套 UI 组件库,包括常用的组件和布局等。
* ArkCompiler:ArkCompiler 是华为自研的统一编程平台,包含编译器、工具链、运行时等关键部件,支持高级语言在多种芯片平台的编译与运行,并支撑应用和服务运行在手机、个人电脑、平板、电视、汽车和智能穿戴等多种设备上的需求。
用于将 TS 代码编译为鸿蒙系统可执行指令,俗称编译打包工具。
初识
准备IDE
按照官方教程,需要下载鸿蒙开发 IDE,也就是 DevEco Studio,和 AndroidStudio 长得差不多,比较容易上手。
首次启动,需要安装 Node.js、ohpm、Harmony OS SDK 等依赖,根据引导一直下一步即可。
完整依赖
* Node.js:鸿蒙使用 TS 作为开发语言,需要 JS 运行环境。
* ohpm:ohpm 全称 Open Harmony Package Manager,也就是鸿蒙上使用的包管理工具,类似Maven 仓库。(前端常用的包管理工具 应该叫npm)
* Harmony OS SDK:相当于 Android 上的 Android SDK。
安装 有一点需要注意,IDE 仅支持特定版本的 Node.js,如果有安装比较高的或者较低的 版本 建议大家先卸载本地安装的 Node.js,通过 IDE 重新安装支持的版本,我自己安装的低版本也会报错
三、创建项目
配置完成后,新建一个项目,比较好的是 把光标放上去还会提示支持哪些设备
Ability 的概念,和 Android 中的 Activity 很像,暂且认为它就是一个页面吧,具体的我还没有学到
除了空页面之外,还支持关于、分类、网格、列表、登录、闪屏等模板。
支持的完整模板
项目配置页面(选择 Empty Ability 下一步)

* Project name:项目名
* Bundle name:项目唯一标志,类似于 Android 的 Package name
* Save location:保存位置
* Compile SDK:编译使用的 SDK 版本
* Model:应用模型,有 Stage 和 FA 可选,官网推荐使用 Stage
* Enable Super Visual:官方的解释是启用低代码开发,先不管它
* Language:开发语言,Stage 模型只能选 ArkTS,FA 模型还可以选 JS
* Compatible SDK:字面意思是兼容的的 SDK 版本,暂时不清楚是最低支持版本(minSdk)还是适配的版本(targetSdk)
* Device type:支持的设备类型
点击 Finish 即可完成创建
创建完的项目结构

鸿蒙中支持多种 Module,常用的有以下两种:
* Entry:相当于 Android 中的 App Module。
* Library:相当于 Android 中的 Library Module,仅可被依赖,无法独立运行。
Stage模型简易结构
动手能力有限,只能粗糙的画一画 :-)

* UIAbility:UIAbility 组件是一种包含 UI 界面的应用组件,主要用于和用户交互。UIAbility 组件是系统调度的基本单元,为应用提供绘制界面的窗口;一个 UIAbility 组件中可以通过多个页面来实现一个功能模块。每一个 UIAbility 组件实例,都对应于一个最近任务列表中的任务。 Android View绘制流程 onLayout onDraw onMesure
* WindowStage:每个 UIAbility 类实例都会与一个 WindowStage 类实例绑定,提供应用进程内窗口管理器的作用。就是说 UIAbility 通过 WindowStage 持有了一个窗口,为 ArkUI 提供了绘制区域。
* Context:Context 是应用中对象的上下文。。。其他还没有考虑到
* Page:Ability 是一个窗口,不包含内容,而 Page 则是真正显示内容的载体,Page 需要依附于 Ability 才能显示。
上手
尝试开发 App 。
UI开发
(类似Android jectpackCompose)
ArkUI 提供了官方组件和布局(举例栅格布局)

APP登录页面开发展示图片
简单介绍
-
鸿蒙使用 struct 定义组件
-
鸿蒙仅支持在 ArkUI 中使用除组件外的特定操作符 if-else、ForEach 、
-
鸿蒙通过组件对象提供的方法设置属性
Text("账号密码登录").fontSize(30).fontColor(Color.Black).width("90%").margin({ top: 20 })
页面配置路由跳转
Ability 和 page。
一般来说一个功能只需要一个 Ability 就够了,目前还没有涉及到多个Ability
page 跳转 (Android Activity启动模式)
鸿蒙提供了 Router 模块,通过 url 地址完成 page 之间的路由。
提供了两种跳转模式,分别是 router.pushUrl() 和 router.replaceUrl(),这两种模式决定了目标页是否会替换当前页。
* router.pushUrl():目标页不会替换当前页,而是压入页面栈。这样可以保留当前页的状态,并且可以通过返回键或者调用 router.back() 方法返回到当前页。
* router.replaceUrl():目标页会替换当前页,并销毁当前页。这样可以释放当前页的资源,并且无法返回到当前页。
同时,Router 模块提供了两种实例模式,分别是 Standard 和 Single。这两种模式决定了目标 url 是否会对应多个实例。
* Standard:标准实例模式,也是默认情况下的实例模式。每次调用该方法都会新建一个目标页,并压入栈顶。
* Single:单实例模式。即如果目标页的url在页面栈中已经存在同 url 页面,则离栈顶最近的同 url 页面会被移动到栈顶,并重新加载;如果目标页的 url 在页面栈中不存在同 url 页面,则按照标准模式跳转。
router.pushUrl({ url:"pages/Main",params:{userName: "name"}}) // 添加params属性,传递参数 }
可以通过调用 router.getParams() 方法来获取传递过来的参数。
获取传递过来的参数对象\
const params: object = router.getParams()
const userName: string = params\["userName"]; // 获取userName的值
重点:变量类型声明 String和string
网络请求
官方提供的 Httpm模块
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
//添加网络权限
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
}
}
async httpWork(URL: string) {
let httpRequest = http.createHttp();
//添加订阅事件
httpRequest.on('headersReceive', (header) => {
console.info('header: ' + JSON.stringify(header));
});
let url = URL;
//GET请求
let promiseGet = httpRequest.request(// 请求url地址
url, {
// 请求方式
method: http.RequestMethod.GET,
// 链接超时 时间
connectTimeout: 60000,
//读取超时 时间
readTimeout: 60000,
// 指定返回数据类型
expectDataType: http.HttpDataType.STRING,
// 是否使用缓存
usingCache: true,
// 优先级 返回[1,1000] 默认为1
priority: 1,
// 使用协议
usingProtocol: http.HttpProtocol.HTTP1_1,
// 是否使用代理
usingProxy: false,
// 添加请求头
header: {
'Content-Type': 'application/json'
}
});
promiseGet.then((data) => {
if (data.responseCode === http.ResponseCode.OK) {
}
}).catch((err) => {
});
}
//POST请求
let promisePost = httpRequest.request(// 请求url地址
url, {
// 请求方式
method: http.RequestMethod.POST,
//如果是POST请求 必须要有请求体
extraData:{
"userName":"zhoutao"
},
// 链接超时 时间
connectTimeout: 60000,
//读取超时 时间
readTimeout: 60000,
// 指定返回数据类型
expectDataType: http.HttpDataType.STRING,
// 是否使用缓存
usingCache: true,
// 优先级 返回[1,1000] 默认为1
priority: 1,
// 使用协议
usingProtocol: http.HttpProtocol.HTTP1_1,
// 是否使用代理
usingProxy: false,
// 添加请求头
header: {
'Content-Type': 'application/json'
}
});
}
promisePost.then((data) => {
if (data.responseCode === http.ResponseCode.OK) {
}
}).catch((err) => {
});
}
//销毁
httpRequest.destroy();
/**
* 网络请求 简单封装
* @param path
* @param method
* @param extraData
* @returns
*/
async requestSync<T>(URL: string, method: http.RequestMethod, extraData?: Object): Promise<Response<T>> {
return new Promise<Response<T>>((resolve, reject) => {
let url = "BaseUrl" + URL;
if (method === http.RequestMethod.POST) {
//因为POST请求必须要有请求体,所以增加一个判断
extraData = {};
}
let httpRequest = http.createHttp();
httpRequest.request(
url, {
method: method,
expectDataType: http.HttpDataType.OBJECT,
header: header,
extraData: extraData
},
(err, data) => {
let res = new Response<T>()
if (!err && data.responseCode === 200) {
Object.assign(res, data.result)
} else {
res.errorCode = data?.responseCode ?? -1
res.errorMsg = err?.message ?? ""
}
resolve(res);
}
)
})
}
}
/**
* 响应处理
*/
export class Response<T> {
errorCode: code = 0
errorMsg: string = ""
data: T = null
isSuccess(): boolean {
return this.errorCode === 0
}
}
数据持久化
App 的状态保存,主要分为 键值对(key value)、 有 Preference、(KVStore、SQL 数据库 使用方法 暂不介绍了)。
* 首选(Preferences)
通常用于保存应用的配置信息。数据通过文本的形式保存在设备中,应用使用过程中会将文本中的数据全量加载到内存中,所以访问速度快、效率高,但不适合需要存储大量数据的场景。
* 键值型数据库(KV-Store)
一种非关系型数据库,其数据以“键值”对的形式进行组织、索引和存储,其中“键”作为唯一标识符。适合很少数据关系和业务关系的业务数据存储,同时因其在分布式场景中降低了解决数据库版本兼容问题的复杂度,和数据同步过程中冲突解决的复杂度而被广泛使用。相比于关系型数据库,更容易做到跨设备跨版本兼容。
* 关系型数据库(RelationalStore)
一种关系型数据库,以行和列的形式存储数据,广泛用于应用中的关系型数据的处理,包括一系列的增、删、改、查等接口,开发者也可以运行自己定义的SQL语句来满足复杂业务场景的需要。
Preferences
接口如下
//初始化
function getPreferences(context: Context, name: string, callback: AsyncCallback<Preferences>): void;
//写入
put(key: string, value: ValueType, callback: AsyncCallback<void>): void;
//检查key和vlue 也就是键值对 key不能为空
has(key: string, callback: AsyncCallback<boolean>): void;
//根据key获取对应的值 如果数据为null 返回默认值
get(key: string, defValue: ValueType, callback: AsyncCallback<ValueType>): void;
//根据对应的key进行删除
delete(key: string, callback: AsyncCallback<void>): void;
//将数据异步存储 持久化
flush(callback: AsyncCallback<void>): void;
//删除初始化数据 持久话数据也会被删除
function deletePreferences(context: Context, name: string, callback: AsyncCallback<void>): void;
//订阅数据,如果相对应key的值发生变化时,会触发 Callback回调
on(type: 'change', callback: Callback<string>): void;
//取消订阅
off(type: 'change', callback?: Callback<string>): void;
用法基本和 Android 中的 SharedPreference 一致,重点是 提供了 on 、 off 来订阅数据变更。 遥遥领先\~\~\~\~
多线程
接口请求、数据存储、埋点上报等等,多线程的性能,直接影响了应用的流畅度。
TaskPool 和 Worker 
TaskPool 支持在主线程封装任务抛给任务队列,系统选择合适的工作线程,进行任务的分发及执行,再将结果返回给主线程,支持任务的执行、取消,工作线程数量上限为 4。
简单使用
import taskpool from '@ohos.taskpool';
/**
* 执行多任务
* @param dataSlice
* @returns
*/
@Concurrent
function printArgs(args: number): number {
return args;
}
function achieve(buffer: ArrayBuffer) {
let number = buffer.byteLength / 3;
let task1 = new taskpool.Task(printArgs, 100);
let task2 = new taskpool.Task(printArgs, 200);
let task3 = new taskpool.Task(printArgs, 300);
taskpool.execute(task1, taskpool.Priority.LOW).then((value: Object) => {
});
taskpool.execute(task2, taskpool.Priority.MEDIUM).then((value: Object) => {
});
taskpool.execute(task3, taskpool.Priority.HIGH).then((value: Object) => {
});
}
Java 中的 ThreadPool 比较类似。
Worker:暂时没有了解
开发体验
优点
* 易上手
* 系统 API 封装性高
系统 API 用起来比较方便。
* TS 学习
可能对于前段开发来说更容易上手。
* 对于Android 开发
IDE 使用基本一致,其次系统架构和 API 定义也非常相似。
缺点
* 系统不开源:开发的时候看不到源码。
* 配套工具还未完善
* 开源框架较少
有待深入了解
more...
笔记到此结束
笔记比较早,项目开发初期草稿,可能落后华为目前的版本
1070





