安卓转做鸿蒙Flutter的这一年

17,676 阅读9分钟

前言

本人作为一个老安卓开发,24年开始转做鸿蒙和Flutter开发。因为工作需要在安卓、鸿蒙和Flutter之间来回游走。经常切换Java、Kotlin、ArkTs、Dart,频繁切换语法习惯还是比较痛苦的,比如创建对象要不要new,要不要加分号,单引号还是双引号 == ! 以下是个人总结,欢迎指正。

一、Android和HarmonyOS对比

  • 开发语言:ArkTS和Java、Kotlin

  • 编程范式:安卓是命令式,鸿蒙是声明式

  • UI框架使用、权限管理、AI相关等

1、关于编程语言

学习ArkTS的主要问题还是文档不够系统,只能先学TypeScript,然后基于TypeScript和ArkTS的差异再进行调整。网上能搜到的一般是TS的资料,对于ArkTS不一定正确。以下是个人感觉差异比较大的地方。

1.1 ArkTs和TS区别

ArkTS是在TypeScript做的扩展,跟标准的Ts的区别主要是放弃了脚本语言动态化的特性,跟Dart有些类似。

  • 强制使用静态类型

  • 禁止在运行时改变对象布局

  • 限制运算符语义

  • 不支持Structural typing(结构化类型)

关于结构类型和名义类型

名义类型系统:数据类型的兼容性或等价性是通过明确的声明和/或类型的名称来确定的。这意味着即使两个类型的结构完全相同,如果它们的名称不同或者没有明确声明它们是相互兼容的,那么它们就被认为是不兼容的。比如Java。

结构类型系统:如果一个类型 Y 具有与类型 X 相同的所有属性,那么类型 Y 被认为是可以赋值给类型 X 的。换句话说,类型的兼容性是通过类型的结构和成员来检查的,而不是通过它们的名字。比如TypeScript。

1.2 ArkTs中的null和undefined

定义

  • 在 TypeScript中,undefined 和 null 是两种不同的类型,也是两个不同的值。undefined 表示变量已经声明,但尚未赋值,或者对象的属性不存在。而 null 表示变量没有任何值,或者说它的值就是“无”。

  • 在非严格比较(==)下,undefined 和 null 是相等的,因为非严格比较会进行类型转换

  • 但在严格比较(===)下,undefined 和 null 是不相等的,因为严格比较不会进行类型转换

相同点:

它们都代表了值的空缺。

在 TypeScript 的默认设置下,它们可以赋值给任何类型,例如 number、string 等。

不同点:

null 通常用来表示一个对象不存在,而 undefined 通常用来表示一个变量没有被赋值,或者一个对象的属性不存在。

1.3 ArkTs中的Object、object

  • object:object类型则用于表示除基本类型外的类型。也就是除 number、string、boolean、symbol、null 或 undefined 之外的类型。

  • Object:Object类型是所有引用类型的基类型。任何值包括除了null和undefined外的基本类型的值(它们会被自动装箱),都可以直接被赋给Object类型的变量。(可以理解成除了null和undefined以外的所有值)

1.4 对象字面量

对象字面量是一个表达式,可用于创建类实例并提供一些初始值。它在某些情况下更方便,可以用来代替new表达式。


class C {

n: number = 0;

s: string = '';

}

let c: C = {n: 42, s: 'foo'};

1.4 关于异步

  • Java主要通过线程和线程池实现异步

  • Kotlin一般是使用协程,避免了线程创建,更轻量

  • ArkTs主要是Promise和async/await,跟Dart类似。创建线程主要是通过TaskPool和Worker。

1.5 关于仓颉

作为华为自研编程语言,现阶段只有小部分公司在尝试,华为也在推广。但是如果没办法带来比较明显的开发效率提升或者app性能提升,编程语言切换的意义就不大了。

2、命令式和声明式

  • 命令式编程是一种编程范式,强调程序的执行过程。在这种范式中,程序员需要明确地告诉计算机每一步应该做什么,如何做。命令式编程关注的是“怎么做”(how to do it),而不是“做什么”(what to do)。常见的命令式编程语言包括 C、Java、Python 等。

  • 声明式编程是一种编程范式,强调程序的目标和结果。在这种范式中,程序员只需要声明程序的目标,而不需要关心具体的执行过程。声明式编程关注的是“做什么”(what to do),而不是“怎么做”(how to do it)。常见的声明式编程语言包括 SQL、HTML、React等。

Android命令式编程,一般习惯使用各种set、update方法直接更新各种控件的数据和UI属性。个人感觉使用比较简单,想更新某个控件直接set值去控制。

HarmonyOS声明式编程,无法直接改动某个控件的样式和数据,只能改变对应的数据状态,而数据状态和UI展示存在映射关系。开发过程中需要考虑要不要拆分不同的数据状态对应不同组件,还有涉及父子组件、兄弟组件、跨层级组件的状态变化,具体场景用什么样的状态修饰更合理。

3、组件使用方面

  • ArkUI组件不是class,无法使用base类、抽象类等方式,只能通过组件嵌套,迭代多了就可能多嵌套一层层base能力的组件。

  • ArkUI中List组件复用使用比较繁琐

  • 部分组件高度默认是屏幕高度,无法像安卓一样高度自适应,需要获取子组件高度然后控制高度。

4、权限管理

跟安卓区别比较大,让用户从管理“权限”到管理“数据”。以图片为例,应用将无法再获取整个图库的访问权限,用户选择哪张照片,应用就得到哪张照片。

  • 提供各类系统Pick,开发者不需要再单独封装。如联系人、拍照、文件管理、图库等。

  • 提供各类安全控件,用在界面内集成对应控件,用户点击后,应用将获得临时授权,从而执行相关操作。

5、AI相关能力

这是安卓不具备的,前期推广阶段基本都是免费的,后期估计会收费。

  • Core Speech Kit(基础语音服务):文本转语音、语音识别

  • Core Vision Kit(基础视觉服务):通用文字识别(识别各类图片文字)、人脸检测、人脸比对以及主体分割等能力。

  • Speech Kit(场景化语音服务):朗读控件(TextReader)和AI字幕控件(AICaption)能力

  • Vision Kit(场景化视觉服务):人脸活体检测能力、卡证识别能力、文档扫描能力和AI识图能力

6、负一屏

负一屏主要展示各种卡片,算是站外流量分发的主要入口。

  • 小米、oppo、荣耀等其他安卓厂商叫快应用,一般通过js开发。

  • 华为升级鸿蒙Next系统后改为元服务,负一屏主要展示元服务卡片,点击一般是打开元服务,也是通过ArkTs开发。主要好处是免安装,有大小限制。

7、AI智能体

  • 小米、oppo、vivo、荣耀等都有自己的智能体,但是有的不对外开放,有的支持力度有限。

  • 鸿蒙提供了小艺智能体,主要分发入口包括推荐卡片、小艺建议、小艺搜索等,开发者可以接入后在合适的时机弹出各类卡片。

8、性能和体验

  • 华为对于app性能和稳定性要求比较高,会针对冷启动、完成时延、卡顿丢帧等指标出性能报告,推动App开发者做优化。并且针对折叠屏适配会有一定的要求。

  • 其他安卓厂商对于性能和折叠屏关注度不高,主要靠各app开发者自己关注。

9、关于今年的鸿蒙化适配

  • 前半年是在各种踩坑爬坑中度过的,现阶段鸿蒙应用市场App完成度也不高,好多App都是先占了坑,里面是各种h5页面。有些公司还处于观望状态,毕竟跟安卓相比日活差太多了,所以投入产出比差太低。

  • 今年升级的鸿蒙Next系统设备数跟华为预期差距还是比较大的,不确定经过明年1年的适配,下年的华为mate系统能不能用纯鸿蒙Next系统。

二、鸿蒙和Flutter

由于多了鸿蒙端导致开发成本的提高,推动了跨端的落地。部分页面在需求迭代过程由native改为Flutter开发,方面后续在鸿蒙端的接入。

1、关于开发体验

  • Flutter和鸿蒙相比,主要问题是嵌套层级太多,设置个圆角、背景色、padding等属性都需要嵌套,感觉比较繁琐。

  • 鸿蒙和Flutter都作为声明式范式,鸿蒙的状态管理通过各类注解,父子组件,兄弟组件等方式分的还是比较细的。Flutter一般通过State、ValueNotifier等方式进行组件更新。

2、Flutter适配及体验

  • Flutter开发的页面完成时延或帧率等性能跟原生比还是有一定差距,主要还是用于二三级页面或者B端App开发。

  • Flutter在鸿蒙端的适配主要是兼容各类channel实现跟Native的通信。当然部分页面或组件在鸿蒙端展示异常就需要单独适配。

三、知识体系(待完善)

1、ArkTS应用

1、应用程序包结构(hap、har、hsp)

2、整体架构

3、开发模型

2、ArkTs

1、基本语法

2、方舟字节码

3、容器类库

4、并发

3、ArkUI

1、基本语法

2、声明式UI描述

3、自定义组件

4、装饰器

5、状态管理

6、渲染控制

4、Stage模型

1、应用配置文件

2、应用组件

3、后台任务

4、进程模块

5、线程模型

5、性能优化

1、冷启动

2、响应时延

3、完成时延

4、滑动帧率

5、包大小