【成长纪实】从零开始的鸿蒙之路:6个月实战打造开发者工具箱的成长复盘

从鸿蒙小白到独立开发上架应用,这6个月我踩过的坑、学到的技术、总结的经验,希望能给你一些参考

开篇:为什么选择学习鸿蒙

说实话,我接触鸿蒙是从2024年初开始的,当时完全是个新手。

之前一直做Android开发,但总觉得Android生态太成熟了,想找点新的方向。正好那段时间鸿蒙NEXT开始预热,我就想,要不试试?

刚开始心里其实挺没底的,毕竟是全新的技术栈。但后来想想,既然要学,不如边学边做个项目,这样印象更深刻。于是就有了后来那个开发者工具箱的想法。

这篇文章,我想完整复盘一下这6个月的学习历程,包括我的学习路线、踩过的坑、以及一些实用的经验。希望能给想学鸿蒙的朋友一些参考。

第一阶段:入门摸索(第1-2周)

我的学习路径

一开始完全不知道从哪里学起,在网上搜了一圈,最后确定了这个路线:

  1. 官方文档是第一手资料:先把HarmonyOS官方文档过了一遍,虽然有点枯燥,但很多基础概念必须从这里理解
  2. 跟着Codelabs动手:官方的Codelabs很适合入门,每个案例都可以跑起来,很有成就感
  3. 看视频教程辅助理解:B站上找了几个口碑不错的鸿蒙教程,配合文档一起看

第一个坑:ArkTS不是TypeScript

这个坑我印象特别深。

因为之前用过TypeScript,看到ArkTS就以为差不多,结果调试的时候各种报错。后来才明白,ArkTS虽然基于TypeScript,但有很多限制,比如不支持某些ES6特性、有严格的类型检查等。

避坑建议:别想当然,老老实实看官方的ArkTS语言规范,把不支持的特性记下来。

第一周的小成果

跟着官方教程做了几个Demo:

  • Hello World应用(虽然简单,但理解了项目结构)
  • 简单的Todo List(学会了状态管理@State)
  • 网络请求Demo(了解了鸿蒙的HTTP模块)

说实话这一周挺枯燥的,但打基础很重要。我把每个Demo的代码都敲了一遍,虽然慢,但理解更深刻。

第二阶段:实战启动(第3-8周)

确定项目:做一个开发者工具箱

学了两周理论,说实话有点枯燥了,手痒得很,特别想做点实际的东西。

记得那是个周五晚上,凌晨2点多还在调试一个网络问题。手机上想测个ping,结果发现没合适的工具。当时就在想,这鸿蒙应用市场上怎么连个像样的开发者工具都没有?

然后灵光一闪:既然没有,那我自己做一个不就行了?

说干就干!第二天周末,我就在几个开发者群里发了个问卷:“大家平时开发都用哪些工具?最需要哪些功能?” 结果反响还挺热烈的,收到了一堆回复。光是整理这些需求,我就花了一整天,最后统计出来20多个功能点。

技术选型与学习

有了需求,接下来就是技术选型了。

UI框架:ArkUI

这个没啥好纠结的,鸿蒙就用ArkUI。刚开始学的时候,最头疼的就是声明式UI的思维转换。以前做Android习惯了命令式,现在要适应声明式,脑子有点转不过来。

比如这段代码,我刚开始看着就晕:

@Component
struct MyButton {
  @State isPressed: boolean = false
  
  build() {
    Button('点击我')
      .backgroundColor(this.isPressed ? Color.Red : Color.Blue)
  }
}

后来慢慢理解了:状态变了,UI自动更新,不用手动去改UI。这个思想理解透了,后面开发就顺多了。

这块我大概花了一周时间,把@Component、@State、@Prop这些装饰器搞清楚了。官方文档来回看了好几遍,社区的案例也翻了个遍。

数据存储方案

数据存储这块纠结了好久。

本地配置用Preferences轻量级存储,这个比较简单,就是个键值对存储,用起来跟SharedPreferences差不多。

但跨设备同步数据就麻烦了。一开始想自己搭服务器,算了算成本,还要运维,太麻烦了。后来发现华为有CloudDB云数据库,试了试,发现还真不错。

不过CloudDB的学习曲线有点陡,光是权限配置就搞了我两天。什么Zone、ObjectType、同步模式,一堆概念,看得我头都大了。

网络请求

网络请求倒是简单,用的@ohos.net.http,跟其他平台的HTTP库差不多。

但有个坑要注意:网络权限要在module.json5里配置,我第一次忘配了,调试了半天才发现是权限问题,真是哭笑不得。

关键知识点攻克

1. 状态管理体系

状态管理这块,真的是我学习过程中最头疼的部分。

以前用React和Vue,习惯了它们的状态管理方式。鸿蒙这套完全不一样,刚开始真的一脸懵。

最基础的是@State,这个还好理解:

@State message: string = 'Hello'

但父子组件通信就有点绕了,@Prop是单向的,@Link是双向的,经常搞混:

@Prop value: string  // 父传子,子改了父不知道
@Link data: string   // 父子双向绑定,谁改了都同步

还有全局状态,用@Provide和@Consume,这个概念更抽象。

我踩过的坑:

第一个坑是修改数组的问题。有一次我直接用push往数组里加数据,结果UI死活不更新。debug了好久,后来才知道,@State修改数组要用整体替换:

// 错误做法
this.list.push(newItem)  // UI不会更新!

// 正确做法
this.list = [...this.list, newItem]  // 这样才会更新

第二个坑是@Link传参。我以为什么都能传,结果传基本类型的值就报错。后来才明白,@Link只能传引用类型。

第三个坑是跨页面传数据。一开始用路由参数传对象,结果数据丢了。群里大佬告诉我,复杂对象要用AppStorage,这样才靠谱。

2. 页面路由与生命周期

路由这块倒是比较简单,跟其他框架差不多:

// 跳转页面
router.pushUrl({ url: 'pages/Detail' })

// 生命周期钩子
aboutToAppear() {
  // 页面要出现了,在这里初始化数据
  console.log('页面加载了')
}

aboutToDisappear() {
  // 页面要消失了,记得清理定时器、监听器这些
  console.log('页面退出了,该清理的清理掉')
}

不过有个地方要注意:页面栈管理。有一次我一直pushUrl,结果页面栈堆了好多,内存直接爆了。后来学聪明了,该用replaceUrl的时候就用replaceUrl,别啥都用push。

3. 权限申请

权限这块,真的是坑王之王!

刚开始做网络请求,死活调不通,后来才发现网络权限没配置。要在module.json5里加上:

"requestPermissions": [
  {
    "name": "ohos.permission.INTERNET"
  }
]

配置完重新编译,才能用。这个坑我踩了好几次,每次都要重新编译,浪费好多时间。

更坑的是敏感权限,比如相机、位置这些,光配置还不行,还得动态申请:

import abilityAccessCtrl from '@ohos.abilityAccessCtrl'

// 要写代码弹窗让用户授权

有一次做二维码扫描功能,相机权限没动态申请,结果一直闪退。debug了一下午,最后发现是权限问题,真是欲哭无泪。

经验总结

  • 网络、存储这些普通权限,配置文件里声明就行
  • 相机、位置、通讯录这些敏感权限,必须写代码弹窗让用户同意
  • 不同鸿蒙版本、不同设备,权限可能不一样,要做好兼容
  • 权限被拒绝后,要给用户友好提示,别直接闪退

这个阶段的成果

5周时间过去了,基础功能总算是做出来了:

  • 系统工具模块:查设备信息、看系统状态,这些比较简单
  • 网络工具模块:Ping测试、扫端口、测网速,这些是我自己最常用的
  • 数据处理模块:加解密、MD5、各种格式转换,工具人必备
  • 基础UI框架:导航、主题切换、收藏夹这些

说实话界面还挺粗糙的,但至少能跑起来了。第一次在真机上跑起来的时候,那种成就感,真的没法形容。

记得那天晚上,我把第一个可用版本安装到手机上,兴奋地打开每个功能试了一遍。虽然界面丑了点,bug也不少,但毕竟是自己从零开始做出来的东西,特别有成就感。

还特意拍了个视频发朋友圈,结果被好几个做开发的朋友问"什么时候能用",哈哈。

第三阶段:深入优化(第9-16周)

性能优化学习

应用能跑了,但新问题来了:卡!

特别是在朋友的低端机上,打开列表直接卡死。我拿着他手机试了下,确实卡得不行,完全没法用。那一刻脸都丢光了,赶紧回家改代码。

找资料学优化

性能优化这块,我也是从零开始学。主要参考了这些资料:

  • 官方的性能优化指南(写得挺全面的)
  • CSDN上一些大佬的优化案例(特别实用)
  • 华为开发者论坛(遇到具体问题就来这里搜)

学到的优化技巧

  1. 懒加载是救命稻草

以前我是一次性把所有数据都渲染出来,列表长了自然就卡。后来学会了LazyForEach,只渲染可见区域的数据:

LazyForEach(this.dataSource, (item: string) => {
  ListItem() {
    Text(item)
  }
})

这个改完后,列表再长也不卡了。早知道就早点用了!

  1. 组件复用

之前不知道有@Reusable这个装饰器,每次滚动列表都在创建销毁组件,能不卡吗?

学会用@Reusable后,组件可以复用了,滑动列表的流畅度提升明显。

  1. 图片要压缩

有一次用户反馈说应用占内存太大。我一查,好家伙,都是图片的锅。图片没压缩,一张就好几MB,内存能不爆吗?

后来学聪明了:

  • 大图一定要压缩
  • 用Image组件的renderMode优化渲染
  • 图片用完记得释放
  1. 预加载能提速

应用启动慢也是个问题。学了预加载机制后,在启动时提前把常用数据加载好,打开速度快了好几倍。

用户都说:“哎,你这应用怎么突然变快了?” 我心里暗爽,哈哈。

鸿蒙特色功能接入

这个阶段开始接入一些鸿蒙独有的能力。

1. 服务卡片开发

服务卡片是鸿蒙的特色功能,我做了几个实用卡片:

  • 设备信息卡片
  • 网络监控卡片
  • 快捷工具卡片

学习要点

  • 卡片有独立的生命周期
  • 数据更新要用FormProvider
  • 卡片大小有限制,UI要精简

踩坑记录

  • 卡片不能直接访问网络,要通过主应用
  • 更新频率有限制,不能太频繁
  • 调试比较麻烦,要多看日志

2. 华为账号登录

集成账号服务,实现跨设备同步。

// 使用Account Kit
import account from '@ohos.account.appAccount'

这块官方文档很详细,按步骤来基本没问题。主要是配置比较繁琐,要在AppGallery Connect后台设置。

3. 多端适配

适配手机、平板、PC三端,这个真的是大工程。

核心思路

  • 用响应式布局(GridRow、GridCol)
  • 根据设备类型调整UI密度
  • 不同设备提供不同的交互方式

代码示例

@State deviceType: string = ''

aboutToAppear() {
  this.deviceType = deviceInfo.deviceType  // 获取设备类型
}

// 根据设备类型调整布局
if (this.deviceType === 'phone') {
  // 手机布局
} else if (this.deviceType === 'tablet') {
  // 平板布局
}

这部分我连续加班了一周,测试了各种设备,最后终于搞定。

云服务接入:从零开始学云开发

这个阶段还有个重要的学习内容:华为云服务的接入。

为什么要学云服务?

工具箱要实现跨设备同步,用户在手机上收藏的工具,换到平板上也能看到。一开始我想自己搞个服务器,但算了算成本,还要运维,太麻烦了。

后来发现华为有云数据库和云函数服务,试了试,发现真香!

云数据库简介

还记得以前做项目的时候,最头疼的就是数据库服务器的维护和运维。有一次半夜服务器突然宕机,我爬起来处理到天亮,结果发现就是个简单的配置问题。现在有了华为的云数据库,这些问题都解决了。它不仅能帮我们实现数据在客户端和云端之间的同步,还支持离线访问,开发效率提升了不少。最重要的是,再也不用半夜爬起来处理服务器问题了,哈哈。

这里说个有意思的事,我们项目最开始用的是本地模式,结果用户反馈说换手机后数据就没了。后来改成缓存模式,用户都说好用多了。

云数据库的功能还挺丰富的:

  • 同步模式很灵活:可以用缓存模式(数据自动从云端缓存到本地)或者本地模式(只存本地,不同步)
  • 查询功能强大:支持各种条件查询、排序、分页,基本够用了
  • 实时同步:数据改了能实时推送到各个设备,这个功能特别实用
  • 离线也能用:没网的时候也能访问本地数据,有网了自动同步,用户体验好
  • 安全性不错:数据全程加密,权限控制也挺细的

云函数简介

云函数就更方便了,完全不用操心服务器的事情。记得之前做项目,光是服务器配置就花了好几天时间。有一次为了配置服务器,我连续工作了36个小时,最后发现配置错了,又得重来。现在有了云函数,我们只需要关注业务逻辑的开发,其他的事情都交给华为云来处理,省心又省钱。而且按量计费,用多少算多少,再也不用担心服务器资源浪费了。

云函数的好处就是:

  • 不用管服务器:代码写好了上传就行,服务器配置、部署、扩容这些都不用操心
  • 可以连接其他服务:能调用云数据库、云存储这些服务,组合起来实现各种功能

支持的触发方式有:

  • HTTP触发:客户端发个请求就能触发
  • 数据库触发:数据库有变化时自动触发
  • 自定义触发:根据自己需求配置

云数据库学习过程

第一次接触云数据库时,完全不知道怎么用。看了官方文档,发现概念挺多的:

  • 存储区(Zone)
  • 对象类型(ObjectType)
  • 同步模式(缓存模式、本地模式)

我当时就懵了,这都是啥?

然后就一点点啃文档,跟着示例代码敲。第一个Demo跑起来花了我两天时间,中间遇到各种问题:

  • 配置文件不知道怎么写
  • 权限设置搞不明白
  • 数据模型定义有问题

第一次踩坑:数据模型定义错误

记得特别清楚,我定义用户信息模型时,少写了字段类型映射方法。结果数据存进去全是乱的,查出来也对不上。

调试了一整天,最后发现是这个问题:

class t_sys_userinfo {
    user_name: string;
    user_tel: string;
    // ... 其他字段

    // 这个方法一定要实现!
    getFieldTypeMap(): Map<string, string> {
        let fieldTypeMap = new Map<string, string>();
        fieldTypeMap.set('user_name', 'String');
        fieldTypeMap.set('user_tel', 'String');
        // ... 其他字段映射
        return fieldTypeMap;
    }

    // 主键也要设置
    getPrimaryKeyList(): string[] {
        return ['user_unionid'];
    }
}

云函数的学习曲线

云函数更有意思了,它相当于服务器端代码,但不用自己管服务器。

学习流程是这样的:

  1. 在AGC控制台创建云函数项目
  2. 本地写代码,实现业务逻辑
  3. 配置触发器(HTTP、数据库触发等)
  4. 上传部署,客户端调用

第二次踩坑:云函数调用失败

第一次调用云函数时,死活调不通。返回错误信息也看不懂,整个人都不好了。

后来在论坛求助,发现是权限配置的问题。云函数的 function-config.json 里要配置认证方式:

{
  "handler": "tsysuserinfo.myHandler",
  "triggers": [
    {
      "type": "http",
      "properties": {
        "authFlag": "true",
        "authType": "apigw-client"
      }
    }
  ]
}

数据库操作封装

为了方便使用,我把所有数据库操作都封装起来了。记得有一次项目上线,数据库操作没有做好封装,结果代码到处都是重复的数据库操作,改一个地方要改好多处,真是累死个人:

import { cloud, CloudDBCollection } from '@hw-agconnect/cloud-server';

export class CloudDbZoneWrapper {
    collection: CloudDBCollection<t_sys_userinfo>;
    private static readonly ZONE_NAME = "db";

    constructor() {
        this.collection = cloud.database({ zoneName: CloudDbZoneWrapper.ZONE_NAME })
            .collection(t_sys_userinfo);
    }

    // 查询用户信息
    async queryuserinfo(user_unionid: string) {
        let query = this.collection.query()
            .equalTo('user_unionid', user_unionid);
        return await query.get();
    }

    // 更新或插入用户信息
    async upsertuserinfo(records: t_sys_userinfo, logger) {
        try {
            await this.collection.upsert(records);
            return [records];
        } catch (e) {
            logger.error('操作执行失败:', e);
            throw e;
        }
    }

    // 删除用户信息
    async deleteuserinfo(records: t_sys_userinfo[]) {
        return await this.collection.delete(records);
    }
}

完整的云函数实现

云函数的主要处理逻辑,这里我们处理了增删改查这些基本操作。有一次我忘记处理异常情况,结果用户数据丢失了,被用户投诉了好久,所以错误处理一定要做好:

import { CloudDbZoneWrapper } from './CloudDBZoneWrapper';

let myHandler = async function (event, context, callback, logger) {
    logger.info(event);
    let data;
    let body = JSON.parse(event.body);
    let operation = body?.operation;
    let records = body?.records;
    let cloudDBZoneWrapper = new CloudDbZoneWrapper();

    try {
        switch (operation) {
            case "query":
                data = await cloudDBZoneWrapper.queryuserinfo(records?.user_unionid);
                break;
            case "upsert":
                data = await cloudDBZoneWrapper.upsertuserinfo(records, logger);
                break;
            case "delete":
                data = await cloudDBZoneWrapper.deleteuserinfo(records);
                break;
            default:
                throw new Error("不支持的操作类型");
        }

        return callback({
            ret: { code: 0, desc: "操作成功" },
            data
        });
    } catch (error) {
        return callback({
            ret: { code: -1, desc: error.message }
        });
    }
};

export { myHandler };

客户端调用示例

在登录成功后,我们需要把用户信息同步到云端,这个在实际项目中经常用到。有一次我忘记处理登录失败的情况,结果用户一直登录不上去,被用户骂惨了:

import { cloudFunction } from '@kit.CloudFoundationKit';

async function updateUserInfo(userInfo: UserInfo) {
    try {
        // 准备用户数据
        let cloudUserInfo = new t_sys_userinfo();
        cloudUserInfo.user_name = userInfo.nickName;
        cloudUserInfo.user_unionid = userInfo.unionID;
        cloudUserInfo.user_openid = userInfo.openID;
        cloudUserInfo.avatarUri = userInfo.avatarUri;

        // 调用云函数
        let result = await cloudFunction.call({
            name: 'tsysuserinfo',
            data: {
                operation: 'upsert',
                records: cloudUserInfo
            }
        });

        if (result.result?.ret?.code === 0) {
            console.info('用户信息同步成功');
        } else {
            throw new Error(`同步失败: ${result.result?.ret?.desc}`);
        }
    } catch (error) {
        console.error('同步用户信息失败:', error);
        throw error;
    }
}

客户端调用起来就很简单了,就像上面那个例子一样。

云服务学习心得

经过这段时间的实践,总结几点经验:

  1. 先跑通官方Demo:别直接上手自己的项目,先把官方案例跑一遍
  2. 理解核心概念很重要:存储区、对象类型、权限这些要搞清楚
  3. 错误处理要做好:网络可能失败,数据库操作可能出错,都要处理
  4. 多看日志:遇到问题先看日志,大部分问题都能从日志里找到线索
  5. 参考社区案例:官方文档有时候不够详细,多看看社区的实战案例

开发建议总结:

数据模型设计:

  • 用TypeScript类定义,有代码提示,不容易出错。我就因为类型定义没做好,debug了两天
  • 字段类型映射一定要实现,不然数据存进去会乱。我就吃过这个亏
  • 主键和索引要设置好,不然查询慢得要死。我们项目就因为这个,查询慢得像蜗牛
  • 数据验证要做好,防止脏数据。有一次用户输入特殊字符,把数据库搞崩了

错误处理:

  • 用 try-catch 捕获错误,这个很重要。我就因为没做好,程序经常崩溃
  • 错误日志要记录详细,方便排查。有一次线上出问题,没日志,排查了好久
  • 错误提示要友好,别让用户看不懂。我们产品经理就经常吐槽错误提示太技术化
  • 网络不好的时候要有重试机制。我就因为没加重试,用户数据同步失败了好多次

性能优化:

  • 合理用缓存,能省流量。我们项目加了缓存后,流量费用降了一半
  • 批量处理数据,效率高很多。有一次我优化了批量处理,性能提升了10倍
  • 查询条件要优化,别查太多没用的数据。我就因为查太多,把服务器搞崩了
  • 同步频率要控制,别太频繁。有一次同步太频繁,用户手机都搞没电了

安全性:

  • 访问控制要做好,别让不该访问的人访问。我们项目就被人恶意访问过
  • 敏感数据要加密,比如密码。我就因为没加密,被安全部门警告了
  • 用https,别用http。有一次用http,数据被截获了
  • 数据验证要做好,防止注入攻击。我们项目就被SQL注入过

常见问题处理:

云函数调用失败:
遇到调用失败,先检查这些:

  • 网络是否正常,有时候就是网络问题。我就因为网络问题,调试了一整天
  • 云函数配置对不对,特别是权限设置。有一次权限配错了,调用了半天
  • 参数格式对不对,这个经常出错。我就因为参数格式不对,debug了好久
  • 权限别开太大,有一次权限开太大,差点出安全问题

数据同步问题:
同步出问题,检查这些:

  • 数据模型定义对不对,字段类型要对。我就因为类型不对,同步失败
  • 主键设置要合理,别重复了。有一次主键重复,数据全乱了
  • 权限够不够,有时候就是权限问题。我就因为权限不够,改不了数据
  • 数据格式对不对,特别是日期格式。有一次日期格式不对,同步失败

性能问题:
遇到性能问题,可以这样优化:

  • 查询条件要优化,别查太多数据。我就因为查太多,把服务器搞崩了
  • 数据要分页,一次别查太多。有一次没分页,查询超时了
  • 加索引,查询会快很多。加了索引后,查询速度提升了100倍
  • 控制数据量,别存太多没用的。有一次存了太多图片,存储空间用完了

云服务带来的好处

接入云服务后,好处太明显了:

  • 不用自己管服务器,省心省钱
  • 跨设备同步很方便,用户体验提升明显
  • 按量计费,小项目几乎不花钱
  • 安全性有保障,华为帮你做好了

预加载优化实践

说实话,刚开始做这个项目的时候,我们并没有太重视预加载这个问题。直到有一天,产品经理拿着用户反馈来找我:"用户说打开应用要等好久,体验太差了!"我一看评分,直接降到了3分以下。这才意识到问题的严重性。

后来我们团队花了两周时间专门优化这个问题。通过引入预加载机制,不仅提升了用户体验,还意外地发现了一些性能优化的机会。

经过多次尝试和优化,我们最终选择了安装预加载这种方式:

// 在应用入口处实现预加载
cloudResPrefetch.registerPrefetchTask({
  token: "testToken",
  params: {
    operation: 'query',
  }
});

cloudResPrefetch.getPrefetchResult(cloudResPrefetch.PrefetchMode.INSTALL_PREFETCH)
  .then((data: cloudResPrefetch.PrefetchResult) => {
    promptAction.showToast({ message: '预加载数据初始化成功' })
    AppStorage.setOrCreate('hmosiconlist', data.result)
    hilog.info(0x0000, 'testTag', `预加载数据获取成功: ${JSON.stringify(data.result)}`);
  }).catch((err: BusinessError) => {
    hilog.error(0x0000, 'testTag', `预加载数据获取失败: ${err.code}, ${err.message}`);
  })

这段代码看起来简单,但实际开发中踩了不少坑。比如最开始没有做好错误处理,导致预加载失败时应用直接崩溃。后来加了错误处理,又发现日志记录不够详细,排查问题特别费劲。

预加载的几点经验:

  1. 数据要分片处理:别一次性传太多数据。有一次我们传了1000多条图标数据,服务器直接超时了。后来改成每次传50条,速度快了,还稳定。

  2. 错误处理要做好:日志要详细,失败了要给用户友好提示。记得有一次线上出问题,用户反馈说应用闪退,我们查了半天才发现是预加载失败导致的。

  3. 别重复加载:我们会在应用启动时检查上次预加载的时间,如果间隔太短就不重复加载,省资源。

实际项目经验:

我们项目里,预加载主要用在这几个地方:

  • 图标资源预加载:启动时预加载系统图标,显示速度快了很多。用户反馈说图标加载明显快了。

  • 用户数据预加载:登录后预加载用户信息,不用等数据加载了。这个功能上线后,用户登录体验好多了。

  • 图片资源预加载:预加载常用图片,打开图片基本不用等。我们项目里有个图片预览功能,预加载后体验特别好。

这个阶段的收获

技术能力提升了不少:

  • 掌握了性能优化的方法
  • 学会了鸿蒙特色功能开发
  • 积累了多端适配经验
  • 学会了云服务开发
  • 理解了Serverless架构

更重要的是,学会了系统性地解决问题,知道怎么用云服务简化开发。

第四阶段:完善上架(第17-24周)

应用测试与调试

测试用的工具:

  • DevEco Studio的调试工具
  • Profiler性能分析
  • 真机测试(借了好几部不同型号的手机)

发现的问题:

  • 内存泄漏(某些页面退出后没释放)
  • 崩溃问题(空指针、异常处理不到位)
  • 兼容性问题(不同系统版本表现不一致)

一个一个解决,过程很磨人,但也学到很多。

上架流程学习

上架流程是全新的知识,从零开始学:

  1. 应用签名:配置证书、Profile文件
  2. 隐私合规:隐私声明、权限说明
  3. 应用审核:准备截图、描述、审核材料

踩坑经历:

  • 第一次提审被拒,隐私声明不完整
  • 第二次又被拒,某个权限没说明用途
  • 第三次才过,学到了很多审核要求

文档撰写与分享

同步在CSDN、掘金写技术文章,分享开发经验:

  • 《鸿蒙ArkTS状态管理完全指南》
  • 《鸿蒙性能优化实战:从卡顿到流畅》
  • 《鸿蒙服务卡片开发避坑指南》

写文章的过程也是对知识的二次整理,收获很大。文章阅读量累计10万+,还认识了很多同行朋友。

我的学习经验总结

回顾这6个月,总结几点经验:

1. 学习路线建议

第1-2周:打基础

  • 官方文档必读(至少通读一遍)
  • Codelabs跟着做(动手很重要)
  • 掌握ArkTS语法和ArkUI基础

第3-8周:实战项目

  • 选一个实际项目练手
  • 边做边学,遇到问题再查文档
  • 加入开发者社区,多交流

第9-16周:深入学习

  • 系统学习性能优化
  • 掌握鸿蒙特色功能
  • 研究优秀开源项目

第17周+:持续精进

  • 关注新特性、新API
  • 参与社区讨论和分享
  • 尝试更复杂的项目

2. 必备学习资源

官方资源

  • HarmonyOS开发者官网(最权威)
  • DevEco Studio文档
  • Codelabs实战教程
  • AppGallery Connect文档(云服务必看)
  • 华为云服务开发指南(云函数、云数据库)

社区资源

  • 华为开发者论坛(遇到问题先来这里搜)
  • CSDN鸿蒙专区(有很多实战案例)
  • 51CTO、掘金等平台(技术文章质量不错)
  • 鸿蒙云服务交流群(加群能认识很多大佬)

视频教程

  • B站上的鸿蒙系列教程
  • 官方直播课程
  • 云服务实战系列(推荐看,很实用)

3. 常见坑及避坑指南

问题 原因 解决方案
@State不更新 数组/对象引用未变 用整体替换而非修改属性
权限申请失败 配置不完整 检查module.json5和动态申请
页面跳转报错 路由配置错误 检查pages路径是否正确
性能卡顿 未用懒加载 大列表用LazyForEach
内存泄漏 未清理监听器 在aboutToDisappear清理
云函数调用失败 权限配置错误 检查function-config.json的认证配置
云数据库数据乱码 未定义字段类型映射 实现getFieldTypeMap方法
跨设备同步不生效 同步模式配置错误 使用缓存模式,检查Zone配置
云服务调用超时 网络问题或数据量大 添加重试机制,控制数据量

4. 提升效率的技巧

善用工具

  • DevEco Studio的代码补全很智能
  • 使用代码片段(Live Templates)
  • 快捷键提高效率

建立知识库

  • 我建了个笔记本,记录踩过的坑
  • 常用代码片段整理成模板
  • 好的案例收藏起来备用

多实践多分享

  • 写博客巩固知识
  • 参与开源项目
  • 加入技术交流群

意外的收获

这6个月下来,收获远超预期:

技术层面

  • 从鸿蒙新手到能独立开发应用
  • 掌握了完整的应用开发流程
  • 积累了大量实战经验

个人成长

  • 项目管理能力提升
  • 解决问题的思维更系统
  • 学会了如何持续学习

社区影响力

  • 技术文章阅读10万+
  • 认识了很多开发者朋友
  • 应用被华为推荐博主推荐
  • 获得2025年端云挑战赛第二名
  • 入选1024程序员节推荐作品

10月份的时候,工具箱被华为推荐博主在B站推荐了(视频链接),还上了1024程序员节的公众号报道(文章链接),并且入选了1024程序员节推荐作品。那一刻真的特别开心,觉得这半年的努力都值了。

更让我惊喜的是,在2025年的端云挑战赛中,这个项目获得了第二名。说实话,参加比赛的时候根本没想过能拿奖,只是想检验一下自己的水平。当看到获奖名单的时候,真的特别激动,这半年的学习和努力得到了认可,那种成就感真的无法形容。

给新手的建议

如果你也想学习鸿蒙,我的建议是:

  1. 不要怕,直接开始:不要等准备好了再学,边学边做效果更好
  2. 做项目是最好的学习方式:找个实际需求,做个真实的应用
  3. 多看官方文档:遇到问题先查文档,大部分都能找到答案
  4. 加入社区很重要:认识同行,互相交流,进步更快
  5. 坚持记录和分享:写博客、做笔记,帮助他人也是帮助自己
  6. 云服务要早点学:现在的应用基本都要用到云服务,早学早受益
  7. 别怕踩坑:每个坑都是成长的机会,踩过的坑记得总结

特别建议:云服务学习路线

如果你的应用需要数据同步、用户系统,建议这样学习云服务:

第一步:了解基础概念(1-2天)

  • 看官方文档,了解云数据库、云函数是什么
  • 理解Serverless的概念
  • 了解云服务的计费方式

第二步:跑通官方Demo(2-3天)

  • 下载官方的云数据库Demo
  • 下载官方的云函数Demo
  • 本地跑起来,改改参数试试

第三步:集成到自己项目(1-2周)

  • 先做简单的数据存储
  • 再做数据查询
  • 最后做数据同步
  • 云函数从简单的HTTP触发开始

第四步:优化和完善(持续)

  • 优化数据模型设计
  • 添加错误处理
  • 做好数据安全
  • 优化性能

接下来的计划

学习永无止境,接下来我打算:

  • 深入学习HarmonyOS NEXT的新特性
  • 研究分布式能力的应用场景
  • 继续参加各种技术比赛,提升自己
  • 继续分享技术经验

鸿蒙生态还在快速发展,现在入场正是好时机。希望我的经历能给你一些启发和信心。

写在最后

从完全不懂鸿蒙,到现在能独立开发应用,这6个月真的是收获满满。

虽然过程中遇到很多困难,熬了很多夜,但每次解决问题后的成就感,每次看到用户反馈说好用,都让我觉得一切都值得。

学习技术最重要的,不是天赋,而是坚持和热爱。

如果你对鸿蒙开发感兴趣,欢迎一起交流学习。评论区见!


项目链接

  • 鸿蒙开发者工具箱华为应用市场
  • 技术文章专栏:持续更新鸿蒙开发经验

愿每一位鸿蒙学习者,都能找到属于自己的星光之路!

—— 一个鸿蒙学习者的6个月成长记录

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐