查看原文
其他

Harmony:关于鸿蒙系统的内容都总结在这里了

鸿洋
2024-09-26

The following article is from Carson带你学Android Author carsonho

本文将普及当前华为鸿蒙系统相关核心内容,包括:

  • 鸿蒙相关概念:如OpenHarmony、Harmony OS、Harmony OS NEXT等;
  • 开发语言:ArkTS
  • 开发框架:ArkUI
  • 开发环境:DevEco-Studio

1鸿蒙相关概念

  • 鸿蒙,即Harmony。日常说的鸿蒙系统特指华为智能终端操作系统,不仅限于手机,而是包括各种设备形式,是跨平台、统一的OS系统。
  • 提及鸿蒙,一般会涉及三个概念:OpenHarmony、Harmony OS、Harmony OS NEXT。

  • 目前市面上大多数鸿蒙系统都是Harmony OS,即因为基于AOSP (Android Open Source Project) 所以可兼容运行Android应用。
  • 所谓的”纯血鸿蒙“,即指Harmony OS除去AOSP后的Harmony OS NEXT,因为除去了AOSP所以不可运行Android应用。

2开发语言:ArkTS

从官方介绍可知:鸿蒙的核心开发语言ArkTS是基于 TypeScript (简称:TS)扩展的。
这里会延伸出两个问题:
  1. TypeScript是什么语言?
  2. TypeScript有什么特点?
  3. 鸿蒙为什么要选TypeScript?

2.1 TypeScript是什么语言?

从官网的介绍可知:TypeScript是从JavaScript扩展而来的开语言。相比于JavaScript,其添加了一大特性:具备类型系统。


所以,ArkTS、TypeScript、JavaScript三者的关系是:TypeScript是JavaScript的超集,而ArkTS则是TypeScript的超集。

2.2 TypeScript有什么特点?

JavaScript 是一门弱类型、动态的编程语言:没有类型约束,这使具备灵活性高特点的同时,也让其在代码的安全性、稳定性带来了很大的挑战。
TypeScript在完整保留 JavaScript 运行时行为的基础上,通过引入类型系统(如静态类型等)来提高代码的可维护性,使代码变得更加稳定和安全,减少可能出现的 bug,并可应用于更大规模的项目。
TypeScript 的核心设计理念:https://github.com/microsoft/TypeScript/wiki/TypeScript-Design-Goals

2.3 鸿蒙为什么要选TypeScript?

鸿蒙系统本身作为一个智能终端系统,其目标是一个跨平台的大统一OS,旨在支持各种设备如手机、平板电脑、智能手表等,其选择开发语言的因素包括:平台兼容性、性能、安全性、开发者使用 & 社区支持。

因素1:兼容性、性能

而JavaScript作为跨平台最受欢迎的语言,其加强版TypeScript的兼容性自然不会有任何问题,同时性能也得到市场的验证。

因素2:安全性

作为安全版的JavaScript,TypeScript一大特点是具备类型系统,即类型安全、是强类型的,所以安全性、稳定性也大大提高。

因素3:开发者使用 & 社区支持

  • JavaScript作为开发者里最受欢迎的语言,具备众多开发社区及开发者,而TypeScript更加甚是,后续无论是推广、开发、维护更新都十分有优势。
  • 同时,TypeScript 的另一个重要的特性就是坚持与 ECMAScript 标准同步发展,这使得使用TypeScript的开发者能第一时间使用到最新的语法特性。
ECMAScript 是 JavaScript 核心语法的标准:https://tc39.es/process-document/,每年都会发布含新语言特性的版本。

另外:TypeScript 是微软基于 Apache 2.0 的开源语言,不会存在任何利益 / 版权问题。

3开发框架:ArkUI


方舟开发框架(简称:ArkUI),它是一套构建 HarmonyOS应用界面的UI开发框架,共分为:

  • 开发模型(即上图中的前端层)
  • 运行时框架(即上图中的核心层、渲染层)
  • 平台适配(即上图中的平台层)
如下所示。

3.1 开发模型

此处主要核心关注ArkUI的开发范式:声明式UI、UI布局、状态管理。

声明式UI

此处结合另外一种常见开发范式说明:命令式 UI。
对于开发一个界面,我们需要关注界面的最终状态 & 通过什么方式去实现这个最终状态。对于上述两种方式的实现过程是:
  • 声明式 UI:关注界面的最终状态,不关注通过什么方式实现(具体实现过程交给框架自动处理)
  • 命令式 UI:关注通过什么具体方式实现。
举个现实例子:假设需要实现每分钟显示一个数字。
  • 声明式 UI:明确每过一分钟显示一个数字的规则即可。
  • 命令式 UI:每等待一分钟即需手动操作显示一个数字,如此循环。
从上面可知,对于大多数开发场景来说声明式 UI更加智能、更加方便,提供了一个更高级别的抽象,简化了开发过程,特别是在复杂界面的开发场景下。具体对比如下:

至于ArkUI内部具体是如何做到状态变化的呢?实际上,在ArkUI命令式框架内部,有两个重要的角色:代理、拦截器。

  • 代理:代理目标视图的数据,并将数据绑定到拦截器上。
  • 拦截器:监听目标数据的变化。
当数据更新时,拦截器就会重写数据的set方法,同时自动更新数据对应的前端页面,从而实现视图的样式、状态的变化。(这整个过程不需要开发者手动命令更新,由ArkUI框架内部自动完成。
类似于Android Compose UI。组件命名从本质概念上也是保持一致的。
build() {
  Column() {
    Text(this.accessText)
      .fontSize(14)
      .fontWeight(FontWeight.Bold)

    if (!this.hasAccess) {
      Button('测试按钮').margin({top: 12})
        .onClick(() => {
          this.reqPermissionsFromUser(this.permissions);
        })
    } else {
      Text('测试文案' )
        .fontSize(14)
        .margin({top: 13})
        .width('100%')
    }
  }
  .height('100%')
  .width('100%')
  .padding(14)
}

UI布局

ArkUI的设计目标是:开发一次代码、多端部署并自适配。这里不得不单独提及ArkUI中UI布局的核心能力:原子布局能力。
实际上,这是一种 使用原子能力、定义元素在不同形态的尺寸界面上体现的自适应规则从而达到在多形态屏幕具备相同设计效果匹配的自适应能力。
比如我定义了 这四个视图元素按照屏幕宽度四等分 的规则,那么在任何尺寸下,这四个视图元素都会四等分屏幕宽度,从而达到相同的设计效果,这种在ArkUI里称为:均分能力 / 布局。
ArkUI的原子布局能力总共分为7种:
  • 均分能力
  • 拆行能力
  • 拉伸能力
  • 缩放能力
  • 延伸能力
  • 占比能力
  • 隐藏能力


状态管理

声明式UI的开发范式使得数据和View可以实现联动更新。

ArkUI为这种联动刷新提供了多维度的状态管理机制,开发者只需通过简单的标注即可实现联动刷新。

3.2 核心层

主要包含:方舟编译运行时、声明式UI后端引擎。

1. 方舟编译运行时

方舟编译的过程 & 描述如下:

2. 声明式UI后端引擎

声明式UI因为由于状态的变化会自动驱动 UI 的变化,而不是开发者手动控制 UI 变化,所以UI性能很大程度上依赖于UI框架对组件树的刷新是否能做到最小更新。
鸿蒙的组件树设计参考了 Flutter典型三棵树框架:Widget - Element - RenderObject,对于鸿蒙来说,则是:Component - Element - RenderNode。

三棵树结构

这里需要特别说明的是,鸿蒙的UI组件Component主要实现是在C++,在C++层对应会有一套UI组件的Component实现。

渲染流程

从创建界面到渲染界面的流程是:
  • 步骤1:页面上的UI组件都对应一个Component,根据Component的嵌套关系会构建出一棵Component树;
  • 步骤2:根据Component树生成Element树,用于管理UI组件的刷新;
  • 步骤3:根据Element树生成RenderNode树,每个Element同时持有Component和RenderNode的信息;
  • 步骤4:最终根据RenderObject树来完成布局排列、绘制和渲染。

为什么要有三棵树?

  • 背景:Component树是面向开发者的,所以经常需要修改,即经常会执行build()。一旦调用build()即意味着该Component依赖的所有其他Widget都会重新创建;
  • 问题:如果直接解析Component树并将其转化为RenderNode树来直接进行渲染,频繁的全量修改&修改那么将会是非常消耗性能;
  • 解决方案:采用树的缓存(Element树),明确真正需要修改的Component部分,再将需要修改的部分同步给RenderNode树进行重新渲染修改部分,最大程度降低对真实渲染视图的修改,提高渲染效率,而不是销毁整个渲染视图树重建。
所以,复用的是Element树,其内部存有Component的状态信息及底层的RenderNode信息,从而减少频繁创建和销毁RenderNode对象(频繁的实例化和销毁 RenderNode十分消耗性能),Component的频繁创建和更改并不会影响性能。

渲染上屏

  • 从渲染上屏前的三棵树结构能看出,ArkUI的渲染架构实际上是参考了Flutter的渲染架构;
  • 实际上Flutter的结构是:Widget -> 三棵树结构 -> Flutter Framework -> Skia,而ArkUI除了参考了三棵树结构,底层的渲染引擎也是用的Skia,只是在使用Skia之前自己写了一套独自的ArkUI,具体如下:

所以ArkUI本身也是通过专门的渲染管线进行自绘制,从而提升整体的应用渲染效果。

据目前最新资讯,华为目前在自研新的渲染引擎,未来研发成功之后会替代 Skia。

4开发环境

主要包括:开发IDE、开发工具、配置文件。

4.1 开发IDE

鸿蒙的开发软件称为:DevEco-Studio,十分类似Android Studio ,同样基于Intellj IDEA开发,界面都长得很类似,不是说很像,而是一模一样。

对于项目文件管理栏,同样可切换Project、Packages应用内视图。

对于底部导航栏,文件管理,日志输出,终端,Profiler都几乎保持一致。

对于SDK Manager,类似于Android Studio,也内建了SDK管理器,可以下载管理不同版本的SDK。

同样的,你也可以通过模拟管理器进行模拟器debug开发。

对于开发IDE,Android人员可以无缝切换进行开发,因为DevEco-Studio跟Android Studio真的长得太像了。

4.2 开发工具

类似Android开发中的adb工具,鸿蒙上的开发工具称为:hdc(HarmonyOS Device Connector),是HarmonyOS为开发人员提供的用于调试的命令行工具,通过该工具可以在windows/linux/mac系统上与真实设备或者模拟器进行交互。
类似命令:
  • hdc list targets
  • hdc file send local remote
  • hdc install package File

命令的名称 & 作用也类似于Android中adb的对应命令,详细命令见:

https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/ide-command-line-hdc-0000001237908229-V3

4.3 配置文件

Android最核心的配置文件是AndroidManifest.xml,其内容是:定义版本号、页面路径、注册了广播和服务,同时还申明了App使用的权限。
同样的,鸿蒙中也对应的配置文件,但与Android的区别是:鸿蒙分为多个文件:build-profile.json5app.json5
对于build-profile.json5,作用是配置Sdk Version和代码模块区分。
{
  "app": {
    "signingConfigs": [],
    "compileSdkVersion": 9,
    "compatibleSdkVersion": 9,
    "products": [
      {
        "name""default",
        "signingConfig""default",
      }
    ],
    "buildModeSet": [
      {
        "name""debug",
      },
      {
        "name""release"
      }
    ]
  },
  "modules": [
    {
      "name""entry",
      "srcPath""./entry",
      "targets": [
        {
          "name""default",
          "applyToProducts": [
            "default"
          ]
        }
      ]
    }
  ]
}
对于app.json5,作用是:模块配置、模块权限和页面名。
{
  "module": {
    "name""entry",
    "type""entry",
    "description""$string:module_desc",
    "mainElement""EntryAbility",
    "deviceTypes": [
      "phone",
      "tablet"
    ],
    "deliveryWithInstall"true,
    "installationFree"false,
    "pages""$profile:main_pages",
    "abilities": [
      {
        "name""EntryAbility",
        "srcEntry""./ets/entryability/EntryAbility.ts",
        "description""$string:EntryAbility_desc",
        "icon""$media:icon",
        "label""$string:EntryAbility_label",
        "startWindowIcon""$media:startIcon",
        "startWindowBackground""$color:start_window_background",
        "exported"true,
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "action.system.home"
            ]
          }
        ]
      }
    ],
    "requestPermissions":[
      {
        "name" : "ohos.permission.APPROXIMATELY_LOCATION",
        "reason""$string:reason",
        "usedScene": {
          "abilities": [
            "FormAbility"
          ],
          "when":"inuse"
        }
      }
    ]
  }
}

至此,关于鸿蒙的各方面内容讲解完毕。

5常见Q&A

很多同学留言私信关于鸿蒙相关问题,包括:要不要学、是否需要转行等等。

问题1:要不要学

从上面可知,因为“纯血鸿蒙“不再支持Android应用,同时基于华为手机目前在国内的覆盖量级,鸿蒙开发几乎是每个应用都必须适配的项目;假设业务需要,大概率会从当前已有的客户端人手抽人力处理。
所以,可以先适当学学,当了解多一项 跨平台新技术;这或许对于客户端、前端开发者来说是一个很好的就业方向及机遇。

问题2:难不难学?

  • 鸿蒙系统的开发框架几乎是采用当前较为流行的开发模式:可读性高的JS、声明式UI,对于有一定经验的客户端 / 前端开发者来说上手难度确实不高;
  • 假设你是从事Android开发,无论从开发模式还是开发工具来看,成本会更加低。


最后推荐一下我做的网站,玩Android: wanandroid.com ,包含详尽的知识体系、好用的工具,还有本公众号文章合集,欢迎体验和收藏!


推荐阅读

学完ASM Tree api,再也不怕hook了
面试题:为什么使用 Bundle 而不使用 HashMap
Android14 VSync 机制深入解读


扫一扫 关注我的公众号

如果你想要跟大家分享你的文章,欢迎投稿~


┏(^0^)┛明天见!

继续滑动看下一个
鸿洋
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存