从入门实践到成为华为开发者专家(HDE),给初学者的学习建议

引言

2024年12月,我获得了华为开发者专家(HDE)认证。

从23年12月开始接触华为鸿蒙生态,到24年4月实战发布首例支持NFC交互的点单元服务,再到24年11月申请并通过华为HDE认证,我想把从初学者到HDE的学习过程记录下来,希望对大家有所帮助。

什么是HDE

官网是这么介绍HDE的:

华为开发者专家(HUAWEI DEVELOPER EXPERTS),简称HDE,是经华为认证的熟悉一种或多种华为开放能力,并对赋能全球开发者有突出贡献的个人,旨在帮助全球开发者成长,构建全球开发者生态。

image.png

HDE是华为开放能力的实践领袖,也肩负起技术布道、知识赋能等责任,除了会在各大技术社区解答用户有关华为开发能力的相关问题,定期也会在社交媒体上进行线上分享,但更多会在线下以讲师的身份来分享关于华为最新技术趋势的观点和见解。

image.png

值得说明的是,和Google的GDE一样,华为的HDE并不是华为的员工,而是一种类似合作伙伴的关系。简单来说,HDE是开发者中具有代表性的一群人,通过华为平台的支持,为华为鸿蒙生态贡献着自己的价值,同时也不断塑造着个人品牌,实现双赢。

如何获得HDE

HDE申请官网:developer.huawei.com/consumer/cn…

HDE的申请条件和流程在官网中均有说明,大概可以分为以下几步:

  1. 提交申请:申请者者在官网填写申请资料;
  2. 信息初审:信息初审通过后,HDE项目组会发送补充资料的邮件,填写补充资料并提交;
  3. 专家复审:补充资料复审通过后,HDE项目组的运营同事会添加申请者的微信,并邀约面试;
  4. 面试:会有华为专家进行线上面试,大概30分钟左右;
  5. 综合评估:HDE项目组对申请者进行最终的评估,并确认是否通过。

HDE认证通过后,将可以在华为开发者官网中看到自己的资料,并且会收到HDE专家认证的电子证书。像下面这张:

image.png

学习建议

内容分为以下几个维度,欢迎大家一起交流学习。

1. 了解 ArKTS 语言

使用ArkTs语言进行开发,了解如下两点即可

1. 数据类型

ArkTS支持的数据类型如下:

Object、string、number、boolean、enum 、Array、union、void、aliases、Record、Map 等。

下面列举一些个例的特性:

// string
undefined == name?:string

// Array
let name: string[] = ['rex','bob']

// union | 联合类型
type Animal = Cat | Dog
let animal : Animal = new Cat()
animal = new Dog()

// aliases | 匿名类型
type Predicate <T> = (x: T) => Boolean;
type NullableObject = Object | null;

// Record<K,V> | Record 与 Map 的区别是 Record 不需要 new,Map 需要 new
let map: Record<string, number> = {
  'John': 25,
  'Mary': 21,
}
2. 语法特点

ArkTS的语法与其他前端语言大同小异,下面列举一些个例的特性:

// Rest参数
fun sum(...numbers: number[])
sum()
sum(1,2,3)
 
// 定义回调
type trigFunc = (x:number) => number
function do_action(f: trigFunc)

// 闭包
function f(): () => number {
  let count = 0;
  return (): number => { count++; return count; }
}
let z = f();
z(); // 返回:1
z(); // 返回:2

// 可选参数
function hello(name?: string) // name == undefined
function multiply(n: number, coeff: number = 2)
nultiply(1)

// 字段不复值时默认值是 undefined

// 构造函数需要使用关键字
constructor(n: string, a: number)

// 模块导出
export let Origin = new Point(0, 0);
export function Distance(p1: Point, p2: Point): number{ *** }

// 模块导入
import * as Utils from './utils' // Utils.X
import { X, Y } from './utils'
X // 表示来自utils的X
Y // 表示来自utils的Y

// 声明
readonly height : number = 1 //只读 
let hi: string = 'hello' //变量
const hello: string = 'hello' //常量

// 空安全
let x: number | null = null

// 接口 interface
interface W {
  bundleName: string
  action: string
  entities: string[]
}
let wantInfo: W = {
  bundleName: 'com.huawei.hmos.browser',
  action: 'ohos.want.action.viewData',
  entities: ['entity.system.browsable']
}

PS:需要注意的是,字符串里插入变量要使用`符号而不是单引号或双引号,如下:

Text(`插入变量到字符串中的值为${this.number}`)

2. HarmonyOS 的项目结构

关于 HarmonyOS 的项目包结构,我们暂时不需要做到全盘掌握,了解如下几个知识点即可:

1. 项目类型

创建项目分为两种类型,分别是 app(应用)、atomicService(元服务

image.png

这两种类型的项目创建后的包结构是一样的,代码编辑也一致。重点差异如下:

  • 元服务类似于微信小程序,用户可直接在手机的负一层页面搜索使用,无需下载
  • 元服务的开发api是应用的开发api的子集,即有些api在开发应用时可用,在开发元服务时不可用。
2. 模块类型

创建模块分为三种类型,分别是 hap、har、hsp

image.png
  • HAP:应用安装和运行的基本单元,分为两种类型:entry和feature
  • HAR:静态共享包 (可以理解为封装的 Library,里面可以存放代码和资源,提供给 hap 或者 har 模块进行引用)
  • HSP:动态共享包(一般应用不常用),和静态包类似,用于封装公共 Library。

静态包和动态包差异点:

  • HAR中的代码和资源跟随使用方编译,如果有多个使用方,它们的编译产物中会存在多份相同拷贝;而HSP中的代码和资源可以独立编译,运行时在一个进程中代码也只会存在一份。
  • 动态包可用于分包模式,例如元服务对每个hap包有大小 2M 的限制,通过分包,preload 的方式满足发布条件。分包链接->
3. 重点文件
  • app.json5 :bundleType 标识 元服务(atomicService)或 应用(app)
  • module.json5 :stage模型模块配置文件,type 标识模块类型(entry、hap、har、share)
  • oh-package.json5 :配置三方包声明文件的入口及包名

最后展示一张项目的包结构截图:

image.png

3. UI 开发中的实用技巧

1. 单位
  • fp: 字体像素单位,随系统字体大小设置变化
  • vp: 密度像素单位
//使用示例
Text('示例').fontSize('16fp').widht('100vp')
2. @Extend

定义扩展组件样式

@Extend(Column)
function ColumnStyle() {
  .width('100%')
  .borderRadius(24)
  .backgroundColor(Color.White)
  .padding({ left: 12, right: 12, bottom: 4, top: 4 })
}

Column(){}.ColumnStyle()
3. @Styles

定义组件重用样式

@Styles fancy() {
  .width(200)
  .height(this.heightValue)
  .backgroundColor(Color.Yellow)
  .onClick(() => {
  this.heightValue = 200
  })
}

Text().fancy()
4. 自定义组件 @Builder 和 @BuilderParam
@Component
struct Child {
  @Builder FunABuilder0() {}
  @BuilderParam aBuilder0: () => void = this.FunABuilder0;

  build() {
    Column() {
      this.aBuilder0()
    }
  }
}

@Entry
@Component
struct Parent {
  @Builder componentBuilder() {
    Text(`Parent builder `)
  }

  build() {
    Column() {
      Child({ aBuilder0: this.componentBuilder })
    }
  }
}
5. 生命周期
  • 自定义组件:@Component装饰的UI单元,可以调用组件的生命周期。
  • 页面:可以由一个或者多个自定义组件组成,只有被@Entry装饰的组件才可以调用页面的生命周期。
    • onPageShow:页面每次显示时触发一次,包括路由过程、应用进入前台等场景,仅@Entry装饰的自定义组件生效。
    • onPageHide:页面每次隐藏时触发一次,包括路由过程、应用进入后台等场景,仅@Entry装饰的自定义组件生效。
    • onBackPress:当用户点击返回按钮时触发,仅@Entry装饰的自定义组件生效。
    • aboutToAppear:组件即将出现时回调该接口,具体时机为在创建自定义组件的新实例后,在执行其build()函数之前执行。
    • aboutToDisappear:aboutToDisappear函数在自定义组件析构销毁之前执行。不允许在aboutToDisappear函数中改变状态变量,特别是@Link变量的修改可能会导致应用程序行为不稳定。

4. HarmoneyOS 的状态管理

1. 组件的状态管理

建议看一遍官网的示例

2. 应用的状态管理

PS:重点提一下 LocalStorage 和 AppStorage 的区别,LocalStorage 是页面级存储、页面内共享,而 AppStorage 是可以跨 Ability 共享的。(即适用于多hap项目)

5. 应用开发中常用方法

1. Toast 的使用
promptAction.showToast({
  message: $r('app.string.success_message'),
  duration: 2000
})
2. Preferences 的使用
import dataPreferences from '@ohos.data.preferences';

//声明
let dataPreferencesManager: dataPreferences.Preferences = {} as dataPreferences.Preferences;

//获取实例
let options: dataPreferences.Options = { name: 'myStore', dataGroupId:'myId' };
dataPreferences.getPreferences(this.context, options, (err: BusinessError, val: dataPreferences.Preferences) => {
    if (err) {
        return;
    }
    preferences = val;
})

//put
dataPreferencesManager.push(key,value)
dataPreferencesManager.flush()
3. Context
/// 实现全局Context
// 在 EntryAbility 的 create 方法中绑定上下文
AppStorage.setOrCreate('context', this.context);

//获取全局Context
AppStorage.get('context')


/// UI页面获取局部Context
const CONTEXT: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
4. JSON 与 Object 的转换
/// JSON to Object
/// 方案一:
class A {
  v: number = 0
  s: string = ''
  fromJson (str: string) {
    let tmpStr: Record<string, Object> = JSON.parse(str);
    if (tmpStr.add != undefined) {
      this.v = tmpStr.v as number;
      this.s = tmpStr.s as string;
    }
  }
}
/// 方案二:
let json: string = '{"name":"rex","age":"10"}'
class Student {
  name: string;
  age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}
let student = JSON.parse(json) as Student;
/// Object to Json(String)
JSON.stringify(any)
5. Http 的使用

由于篇幅原因,网络请求的封装使用,建议看我的这篇文章# HarmonyOS :面向对象式网络请求库,我发布的第一个鸿蒙三方库

6. 路由框架的使用

由于篇幅原因,路由框架的封装使用,建议看我的这篇文章# 探索HarmonyOS:一键掌握Router与NavPathStatck的传参和页面回调技巧

开源代码示例

提供给初学和进阶者的开源代码示例

GitHub:https://github.com/liyufengrex/HarmonyAtomicService

GitCode:https://gitcode.com/liyufengrex/HarmonyAtomicService

(基于API11开发,支持NEXT及以上版本运行)已上传可供参考,包含如下内容:

  • 静态库+动态包+多模块设计
  • 状态管理
  • 统一路由管理(router+navPathStack)
  • 网络请求、Loading 等工具库封装
  • 自定义组件、自定义弹窗(解耦)
  • EventBus 事件通知
  • 扩展修饰器,实现 节流、防抖、权限申请
  • 动态路由 (navPathStack + 动态import + WrappedBuilder)
  • UI动态节点操作 (BuilderNode + NodeController)
  • 折叠屏适配示例
  • 组件工厂示例
  • 组件动态属性设置示例
  • 云函数、云数据库使用示例
  • 华为账号服务示例(快速登陆、快速验证手机号)

有兴趣的同学也可以关注我的「HarmonyOS开发专栏」,内容持续更新

image.png

写在结尾

我希望我的文章能够帮到更多的人,特别是像我一样对生活充满着迷茫的人,我希望我走过的一些可能正确的路能让你少走一些弯路。当然我也希望你也能清楚的知道,任何事物的成功,有时候努力是一部份,运气也是一部份。

人生是一场游戏,不要着相。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,843评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,538评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,187评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,264评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,289评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,231评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,116评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,945评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,367评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,581评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,754评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,458评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,068评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,692评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,842评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,797评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,654评论 2 354

推荐阅读更多精彩内容