鸿蒙原生开发实战宝典:AI菜谱生成器全攻略——兼谈鸿蒙PC适配与鸿蒙Flutter框架选型


本文以AI菜谱生成器为实战案例,从鸿蒙原生ArkTS开发、鸿蒙PC端适配、离线Mock方案、性能优化到鸿蒙Flutter框架对比,全方位解析鸿蒙生态下美食工具类应用的开发全流程。
引言
民以食为天。在中国,"吃"从来都不是一件小事。从清晨的豆浆油条,到深夜的烧烤大排档,美食贯穿了中国人生活的方方面面。而随着生活节奏的加快,越来越多的年轻人开始走进厨房,尝试自己动手做饭。
但做饭这件事,说简单也简单,说难也难。很多人都有过这样的经历:打开冰箱,看着里面零零散散的食材,却不知道该做什么菜;或者想做某道菜,却不知道具体的步骤和火候。这时候,如果有一个智能助手,能够根据你现有的食材,自动推荐合适的菜谱,告诉你每一步该怎么做,那该有多好?
AI菜谱生成器,就是为了解决这个痛点而生的。
在鸿蒙生态蓬勃发展的今天,美食工具类应用正迎来新的机遇。随着鸿蒙PC的正式发布,鸿蒙操作系统正式进入桌面时代,从手机、平板、手表、智慧屏,到如今的PC,鸿蒙正在构建一个覆盖全场景的智慧生活生态。而美食,作为日常生活中最高频的场景之一,自然是鸿蒙生态中不可或缺的一部分。
想象一下这样的场景:你在下班路上,用鸿蒙手机打开AI菜谱生成器,输入家里现有的食材,AI为你推荐了几道合适的菜;回到家,鸿蒙PC上的菜谱应用自动同步,你用大屏幕看着详细的步骤,一边做菜一边跟着学;做好之后,用智慧屏给家人展示你的成果,甚至可以一键分享到家庭圈。
这样的全场景美食体验,只有在鸿蒙生态中才能实现。
本文将以AI菜谱生成器为线索,带你深入鸿蒙原生开发的世界。我们将从项目架构设计开始,逐步拆解每一个核心功能的实现原理,探讨鸿蒙PC端的适配策略,对比分析鸿蒙原生ArkTS与鸿蒙Flutter框架的优劣取舍,最后展望鸿蒙生态下美食工具类应用的未来发展方向。
无论你是已经有一定鸿蒙开发基础、想深入理解PC端适配的开发者,还是对鸿蒙生态充满好奇、想寻找切入点的技术爱好者,亦或是正在为新项目做技术选型的团队负责人,都能在本文中找到有价值的内容和思考。
让我们一起,从一款小小的AI菜谱生成器出发,探索鸿蒙生态下美食应用的无限可能。
第一章 鸿蒙PC生态与美食应用的新蓝海
1.1 鸿蒙全场景战略的美食版图
要理解美食应用在鸿蒙生态中的位置,我们必须先回到鸿蒙操作系统的初心——全场景智慧生活。
早在2019年鸿蒙系统首次发布时,华为就明确了其定位:这不是又一个手机操作系统,而是一个面向全场景的分布式操作系统。鸿蒙的目标,是覆盖人们生活的方方面面——出行、办公、娱乐、家居、健康,当然,也包括美食。
美食,是人类最基本的需求之一,也是最高频的生活场景之一。据统计,中国人每天花在"吃"相关事情上的时间,平均超过2小时。从买菜、做饭,到吃饭、分享,美食贯穿了人们日常生活的始终。
在鸿蒙的全场景版图中,美食场景有着独特的重要性:
首先,美食是最高频的生活场景之一。几乎每个人每天都要和"吃"打交道。高频的场景,意味着更多的用户接触点,也意味着更多的商业机会。
其次,美食场景天然适合多设备协同。做饭这件事,往往不是在一个设备上完成的——你可能用手机查菜谱,用平板看步骤,用智慧屏跟着学,用智能秤称食材,用智能烤箱烤东西。鸿蒙的分布式能力,正好能够将这些设备串联起来,形成完整的美食体验闭环。
第三,美食具有很强的社交属性。中国人喜欢分享美食,喜欢晒美食,喜欢和家人朋友一起吃饭。美食应用天然具备社交传播的潜力,这对于鸿蒙生态的用户增长来说,是非常有利的。
随着鸿蒙PC的发布,美食场景的版图又扩大了一块。PC端是内容消费和创作的重要阵地,很多人喜欢在电脑上看菜谱、学做菜。大屏幕、全键盘、多窗口,这些PC端的优势,能够让美食应用的体验更上一层楼。
可以预见,在未来的鸿蒙生态中,美食类应用将占据重要的一席之地。而AI菜谱生成器这样的工具型应用,正是切入美食赛道的绝佳起点。
1.2 鸿蒙PC的技术特点与美食应用的契合点
鸿蒙PC的发布,标志着鸿蒙生态正式进入桌面时代。那么,鸿蒙PC究竟有哪些技术特点?这些特点又与美食应用有哪些契合点呢?
统一的系统架构,一次开发多端部署
鸿蒙PC与鸿蒙手机、平板采用完全相同的系统内核和技术栈。这意味着,开发者不需要为PC端重新学习一套全新的开发技术,只需要掌握ArkTS + ArkUI,就能够开发适配所有鸿蒙设备的应用。
对于美食应用来说,这意味着什么?意味着你开发的菜谱应用,可以同时运行在手机、平板、PC、智慧屏等多种设备上。用户在手机上收藏的菜谱,在PC上也能看到;用户在PC上创建的菜单,也能同步到手机上。这种"一次开发,多端部署"的特性,大大降低了开发者的适配成本,也提升了用户的跨设备体验。
分布式能力的全面释放
在鸿蒙PC上,分布式能力得到了更充分的发挥。你可以在PC上直接编辑手机里的照片,可以用PC的键盘和鼠标操作平板上的应用,可以把PC的屏幕无缝扩展到智慧屏上。
对于美食应用来说,分布式能力有着巨大的想象空间:
- 跨设备数据同步:在手机上收藏的菜谱,自动同步到PC和平板。
- 跨设备能力调用:用手机拍照识别食材,结果直接显示在PC的菜谱应用中。
- 多屏协同:PC屏幕显示菜谱步骤,平板屏幕显示食材称重,智慧屏播放教学视频,多屏配合,让做饭更高效。
- 一碰传:手机碰一下PC,就能把菜谱"流"过去,接着刚才的进度继续看。
这些分布式能力,能够让美食应用的体验发生质的飞跃,从"一个菜谱App"变成"全场景的厨房助手"。
原生的AI能力集成
鸿蒙系统深度集成了华为的AI引擎,提供了丰富的原生AI能力接口。对于美食应用来说,这意味着你可以直接调用系统级的AI能力,而不需要自己搭建复杂的AI模型。
比如: - 图像识别:用摄像头拍一张食材的照片,AI自动识别是什么食材。
- 语音交互:用户用语音说"我想吃番茄炒蛋",应用自动调出对应的菜谱。
- 智能推荐:根据用户的口味偏好、历史记录,智能推荐合适的菜谱。
- 营养分析:自动分析菜品的营养成分,给出健康建议。
这些AI能力,能够大大提升美食应用的智能化水平,让应用变得更聪明、更好用。
桌面级的交互体验
鸿蒙PC针对桌面使用场景做了大量优化,包括窗口管理、多任务处理、键鼠交互、文件系统等。
对于美食应用来说,PC端的交互优势非常明显: - 大屏幕:菜谱的步骤、图片都可以展示得更清晰,用户看得更舒服。
- 多窗口:一边看菜谱,一边查食材的营养价值,一边和朋友聊天,多任务并行。
- 键鼠操作:搜索菜谱、输入食材、编辑菜单,键盘鼠标的效率比触屏高得多。
- 文件管理:菜谱可以保存为文件,方便分享和打印。
可以说,鸿蒙PC的这些技术特点,与美食应用的需求高度契合。美食应用在鸿蒙PC上,能够获得比在手机上更好的体验。
1.3 美食工具类应用的市场机会
聊完了技术,我们来聊一聊市场。美食工具类应用,究竟有多大的市场机会?
首先,用户基数大。民以食为天,几乎每个人都是美食应用的潜在用户。无论是刚学做饭的厨房新手,还是追求品质的美食达人,都能从美食工具类应用中找到自己需要的东西。
其次,使用频率高。吃饭是每天都要做的事情,对应的美食应用也有很高的使用频率。高频的使用,意味着更高的用户粘性,也意味着更多的商业变现机会。
第三,商业化路径清晰。美食应用的商业化路径非常清晰: - 食材电商:推荐菜谱的同时,推荐对应的食材,做电商导流。
- 厨房用品:推荐好用的厨房工具、电器,做带货。
- 付费内容:高级菜谱、烹饪课程、营养师咨询等付费内容。
- 本地生活:推荐附近的餐厅、菜市场、生鲜配送等。
- 广告变现:品牌广告、效果广告等。
这些商业化路径,都已经被市场验证过是可行的。
第四,鸿蒙生态的红利期。鸿蒙应用市场还处于快速成长期,竞争相对较小,新应用更容易获得曝光和用户。对于独立开发者和小团队来说,这是一个抢占先机的好时机。
特别是在美食工具这个细分领域,目前鸿蒙平台上的优质应用还不多。如果能够做出一款体验优秀、功能实用的AI菜谱生成器,很有机会在这个赛道上脱颖而出。
当然,机会大,挑战也不小。美食应用的市场虽然大,但竞争也很激烈。要想在众多应用中脱颖而出,需要有自己的特色和核心竞争力。
AI菜谱生成器的核心竞争力是什么?我们认为,有以下几点:
第一,智能匹配。根据用户现有的食材,自动推荐合适的菜谱。这解决了用户"不知道做什么菜"的痛点,是非常实用的功能。
第二,简单易用。打开就能用,不需要复杂的注册登录,不需要繁琐的设置。轻量化的工具型应用,即用即走。
第三,全场景体验。借助鸿蒙的分布式能力,实现多设备无缝协同。这是其他平台的应用做不到的,也是鸿蒙应用的独特优势。
第四,持续迭代。不断优化算法,增加菜谱数量,丰富功能,让应用越来越好用。
如果能够把这几点做好,AI菜谱生成器完全有机会在鸿蒙生态的美食赛道上占据一席之地。
1.4 AI菜谱生成器的产品定位
在众多美食应用中,AI菜谱生成器是一个什么样的定位呢?
我们认为,AI菜谱生成器的核心定位是:轻量化的智能厨房助手。
具体来说,有以下几个关键词:
轻量化
AI菜谱生成器不是一个大而全的美食平台,而是一个小而美的工具型应用。它功能聚焦,操作简单,打开就能用,用完就走。
用户不需要注册登录,不需要填写个人信息,不需要关注一大堆东西。输入食材,生成菜谱,就这么简单。
这种轻量化的产品形态,非常符合鸿蒙生态的应用调性,也非常适合作为用户手机上的"常备工具"。
智能化
AI菜谱生成器的核心是"AI"。它不是一个静态的菜谱库,而是能够根据用户的输入,智能推荐合适的菜谱。
随着AI技术的不断升级,未来的AI菜谱生成器可以做得更智能: - 图像识别食材,不用手动输入
- 根据用户口味偏好,个性化推荐
- 自动调整菜谱的分量和难度
- 智能搭配一日三餐,保证营养均衡
智能化,是AI菜谱生成器区别于传统菜谱应用的核心特征。
实用导向
AI菜谱生成器的所有功能,都围绕着"实用"二字。它不是用来"逛"的,而是用来"用"的。
用户打开这个应用,目的很明确:我有这些食材,我想知道能做什么菜,怎么做。我们的目标,就是帮助用户最快地解决这个问题。
因此,我们的产品设计,一切以效率为导向。减少不必要的步骤,去掉华而不实的功能,让用户能够最快地得到想要的结果。
全场景
虽然现在的AI菜谱生成器还只是一个单设备的应用,但从长远来看,它的目标是成为全场景的厨房助手。
借助鸿蒙的分布式能力,AI菜谱生成器可以在手机、平板、PC、智慧屏、智能厨房设备之间无缝流转,为用户提供连贯的、多设备协同的美食体验。
这是AI菜谱生成器的长期愿景,也是它的潜力所在。
总结一下,AI菜谱生成器的产品定位是:以智能匹配为核心,以实用高效为导向,以轻量化为形态,以全场景为目标的智能厨房助手。
这个定位,决定了我们后续的产品设计和技术选型。在接下来的章节中,我们将看到,这样的定位是如何体现在每一个功能、每一行代码中的。
第二章 鸿蒙原生ArkTS开发实战
2.1 项目架构设计
任何一个应用的开发,都始于架构设计。好的架构,能够让后续的开发事半功倍;而糟糕的架构,则会让项目在后期陷入无尽的"技术债务"中。
对于AI菜谱生成器这样的单页面应用,我们采用了分层架构的设计思想,将代码分为以下几个层次:
数据层(Data Layer)
数据层是整个应用的数据基础,负责数据的定义和存储。
在AI菜谱生成器中,数据层包括:
- 接口定义:Recipe、GenParams、HistoryItem等核心接口的定义。
- Mock数据:内置的菜谱数据库。
- 本地存储操作:preferences的读写逻辑。
数据层的职责很单一:就是管好数据。它不关心业务逻辑,也不关心UI展示。
服务层(Service Layer)
服务层负责业务逻辑的封装,是连接数据层和视图层的桥梁。
在AI菜谱生成器中,服务层包括: - RecipeApiService:菜谱生成的API服务接口。
- 匹配算法:根据用户输入的食材,匹配最合适的菜谱。
- 工具函数:时间格式化、字符串处理等通用工具。
服务层封装了所有的业务逻辑,对上层提供统一的接口。这样,当业务逻辑发生变化时(比如把Mock换成真实API),只需要修改服务层,不需要动UI层。
视图层(View Layer)
视图层负责UI的渲染和用户交互,也就是我们的Index.ets页面组件。
视图层包括: - 布局结构:页面的整体布局和组件结构。
- 样式设计:颜色、字体、间距等视觉样式。
- 交互逻辑:按钮点击、输入变化、列表滚动等用户交互。
视图层的代码,应该尽量保持"薄"——只负责展示和交互,不包含复杂的业务逻辑。复杂的业务逻辑,都应该下沉到服务层。
状态层(State Layer)
状态层负责页面状态的管理。
在AI菜谱生成器中,由于是单页面应用且状态不复杂,我们直接使用@State装饰器进行轻量化状态管理,没有引入额外的状态管理方案。
状态层的变量包括:输入的食材、当前展示的菜谱、收藏列表、历史记录、生成中状态、收藏面板显示状态等。
这种分层架构的好处是职责清晰,易于维护。当需要修改某个功能时,你知道该去哪一层找代码;当需要替换某个实现时,你只需要修改对应层的代码,不会影响其他层。
当然,对于这样一个简单的单页面应用,我们没有必要把分层做得过于复杂。所有代码都写在一个Index.ets文件中,也是完全可以的。重要的是,在写代码的时候,心中要有分层的意识,保持代码的清晰和可维护性。
2.2 核心数据结构设计
数据结构是应用的骨架。设计好数据结构,后续的开发就有了坚实的基础。
在AI菜谱生成器中,我们定义了以下几个核心接口:
Recipe接口
Recipe接口表示一道完整的菜谱,是应用中最核心的数据结构。
interface Recipe {
id: number;
name: string;
ingredients: string[];
steps: string[];
difficulty: string;
time: string;
}
让我们来看一下每个字段的含义: - id:菜谱的唯一标识符,用于区分不同的菜谱。
- name:菜名,比如"番茄炒蛋"、“红烧肉”。
- ingredients:食材列表,一个字符串数组,每个元素是一种食材。
- steps:烹饪步骤列表,一个字符串数组,每个元素是一个步骤。
- difficulty:难度,比如"简单"、“中等”、“困难”。
- time:耗时,比如"15分钟"、“60分钟”。
这个接口的设计,考虑了以下几个因素: - 完整性:包含了展示一道菜谱所需要的所有信息。
- 扩展性:如果后续需要增加新的字段(比如图片、营养信息等),可以直接在接口中添加。
- 易用性:数组结构便于遍历和展示。
GenParams接口
GenParams接口表示生成菜谱的参数。
interface GenParams {
ingredients: string;
}
这个接口很简单,只有一个ingredients字段,表示用户输入的食材。
为什么要单独定义这个接口,而不是直接传字符串呢?主要是为了扩展性。未来,如果生成菜谱需要更多的参数(比如人数、口味、难度等),可以直接在这个接口中添加,不需要修改函数签名。
HistoryItem接口
HistoryItem接口表示一条历史记录。
interface HistoryItem {
id: number;
recipeName: string;
ingredients: string;
timestamp: number;
}
每个字段的含义: - id:历史记录的唯一标识符。
- recipeName:生成的菜谱名称。
- ingredients:用户输入的食材。
- timestamp:生成时间的时间戳。
为什么历史记录不直接保存完整的Recipe对象呢?主要是为了节省存储空间。历史记录只需要展示基本信息,不需要完整的菜谱数据。如果用户想看完整的菜谱,可以重新生成,或者从收藏中查找。
RecipeApiService接口
RecipeApiService接口定义了菜谱生成服务的接口规范。
interface RecipeApiService {
fetchRecipe(params: GenParams): Promise;
}
这个接口只有一个方法:fetchRecipe。传入GenParams参数,返回一个Promise,Promise的结果是Recipe对象。
定义这个接口的好处是: - 面向接口编程:上层代码依赖的是接口,而不是具体的实现。
- 易于切换实现:Mock实现和真实API实现都遵循同一个接口,切换时不需要修改上层代码。
- 易于测试:可以很方便地用Mock实现来替代真实实现,进行单元测试。
可以看到,每个接口都有明确的职责和设计考量。好的数据结构设计,能够让代码更清晰、更健壮、更易于扩展。
2.3 页面布局与组件设计
AI菜谱生成器的页面布局,采用了上下结构的设计: - 顶部标题栏:左侧是应用标题和副标题,右侧是"我的收藏/返回生成"切换按钮。
- 中间内容区:根据当前状态,显示生成区域或收藏列表。
- 底部提示栏:显示当前运行模式等提示信息。
这种布局结构清晰,操作路径短,用户能够快速找到自己需要的功能。
在生成区域,我们又做了进一步的细分: - 食材输入区:多行文本输入框,用户在这里输入现有的食材。
- 生成按钮:一键生成菜谱的主操作按钮。
- 菜谱展示区:展示生成的完整菜谱,包括菜品信息、食材清单、分步做法。
- 历史记录区:展示最近的生成历史。
在组件的选择上,我们尽量使用鸿蒙原生的基础组件,保持应用的轻量化: - Text:用于展示各种文本内容。
- TextArea:用于食材的输入。
- Button:用于各种操作按钮。
- Column / Row / Flex:用于布局排列。
- List / ListItem:用于历史记录和收藏列表的展示。
- ForEach:用于列表数据的循环渲染。
这些都是ArkUI中最基础、最常用的组件,性能好,稳定性高,完全能够满足我们的需求。
在UI设计上,我们采用了暖橙色主题(#FF6B35)。为什么选择橙色?因为橙色是美食的代表色,能够唤起人们的食欲,给人温暖、活力的感觉。这与菜谱应用的定位非常契合。
具体的设计细节包括: - 主色调:暖橙色 #FF6B35,用于按钮、标签、步骤编号等重点元素。
- 背景色:浅灰色 #F7F7F7,柔和不刺眼。
- 卡片色:白色 #FFFFFF,搭配浅阴影,层次分明。
- 文字色:深灰色 #333333 为主,浅灰色 #999999 为辅,保证可读性。
- 圆角设计:卡片、按钮、标签都使用圆角,给人柔和、亲切的感觉。
- 卡片阴影:轻微的阴影效果,增加层次感和立体感。
这些设计细节,共同构成了AI菜谱生成器温馨、清新、有食欲感的视觉风格。
2.4 状态管理方案选型
状态管理,是前端开发中永恒的话题。在鸿蒙开发中,我们同样面临着状态管理方案的选择。
鸿蒙提供了多种状态管理的装饰器,包括@State、@Prop、@Link、@Provide、@Consume、@Observed、@ObjectLink等。此外,还有更复杂的状态管理方案,比如AppStorage、LocalStorage,以及第三方的状态管理库。
对于AI菜谱生成器这样的单页面应用,我们的选择是:仅使用@State装饰器,进行轻量化状态管理。
为什么做出这样的选择?主要有以下几个考虑:
第一,应用简单,状态不多。整个应用只有寥寥几个状态变量:输入的食材、当前展示的菜谱、收藏列表、历史记录、生成中状态、收藏面板显示状态、当前菜谱是否已收藏。这些状态都在同一个组件内,不需要跨组件传递。用@State完全够用。
第二,保持轻量化。引入复杂的状态管理方案,会增加代码的复杂度和学习成本。对于这样一个简单的应用,“杀鸡焉用牛刀”?过度设计,反而会降低开发效率和代码的可维护性。
第三,符合产品定位。AI菜谱生成器的定位是"轻量化工具",对应的,我们的技术方案也应该是轻量化的。简单、直接、高效,这才是工具型应用该有的样子。
在我们的代码中,所有的状态变量都用@State装饰,定义在组件内部:
@State inputIngredients: string = ‘’;
@State currentRecipe: Recipe | null = null;
@State favoriteRecipes: Recipe[] = [];
@State historyList: HistoryItem[] = [];
@State isGenerating: boolean = false;
@State showFavorites: boolean = false;
@State isFavorite: boolean = false;
每个状态变量都有明确的类型和初始值,职责单一,易于理解。状态的修改也都封装在组件内部的方法中,逻辑清晰,追踪方便。
当然,这并不是说复杂的状态管理方案不好。如果你的应用很复杂,有很多跨组件、跨页面的状态需要共享,那么引入更强大的状态管理方案是完全必要的。
但对于AI菜谱生成器这样的应用,@State就是最佳选择。它简单、直接、高效,能够让你把更多的精力放在业务逻辑和用户体验上,而不是纠结于状态管理的架构。
这种轻量化的状态管理方式,对于中小型工具型应用来说,是非常值得推荐的。
第三章 AI菜谱生成器核心功能深度解析
3.1 智能匹配算法设计
智能匹配,是AI菜谱生成器最核心的功能。用户输入食材,系统自动推荐最合适的菜谱——这个"自动推荐"是怎么实现的呢?
在当前的离线Mock模式下,我们实现了一个简单但有效的食材匹配算法。虽然还达不到真正AI的智能程度,但对于Mock版本来说,已经足够好用了。
算法的基本思路是:将用户输入的食材,与每道菜的食材进行比对,计算匹配度,匹配度最高的那道菜就是推荐结果。
具体的实现步骤是这样的:
第一步:解析用户输入
用户输入的是一个字符串,可能用逗号、顿号、空格等分隔。我们需要先把这个字符串拆分成一个个独立的食材。
const inputList: string[] = inputIngredients.split(/[,,、\s]+/).filter((item: string) => item.length > 0);
这里我们用了一个正则表达式 /[,,、\s]+/ 来分割字符串。这个正则表达式的意思是:遇到逗号、中文逗号、顿号、空白字符(空格、换行等),就进行分割。这样,无论用户用什么分隔符,都能正确解析。
分割之后,我们还用filter过滤掉了空字符串,避免因为连续的分隔符产生空元素。
第二步:遍历所有菜谱,计算匹配度
对于每一道菜,我们计算它与用户输入的匹配度。匹配度用"匹配的食材数量"来衡量——匹配的食材越多,说明这道菜越合适。
具体的比对逻辑是这样的:对于用户输入的每一种食材,我们检查这道菜的食材列表中是否包含这种食材。如果包含,匹配数就加1。
为了提高匹配的灵活性,我们还做了模糊匹配:不要求完全相等,只要一方包含另一方就算匹配。比如用户输入"蛋",可以匹配到"鸡蛋";用户输入"西红柿",也可以匹配到"番茄"(当然,这个例子需要同义词库,我们当前的实现还做不到这么智能,但基本的包含匹配已经实现了)。
if (recipe.ingredients[k].includes(input) || input.includes(recipe.ingredients[k])) {
matchCount++;
break;
}
第三步:选出匹配度最高的菜谱
遍历完所有菜谱后,我们找出匹配数最多的那道菜,作为最终的推荐结果。
如果有多道菜的匹配数相同怎么办?我们的处理是:取匹配数相同的第一道菜。这是一个简单的处理方式,在Mock版本中完全够用。在真实的AI版本中,可以用更复杂的排序策略(比如按热门程度、按用户偏好等)。
这个算法虽然简单,但有几个优点:
第一,效果还不错。对于常见的食材组合,都能推荐出比较合适的菜谱。比如输入"番茄 鸡蛋",会推荐番茄炒蛋;输入"土豆 青椒",会推荐青椒土豆丝。
第二,性能很好。算法的时间复杂度是O(n*m),其中n是菜谱数量,m是用户输入的食材数量。对于内置的8道菜谱来说,完全是小菜一碟,瞬间就能出结果。
第三,易于理解和维护。算法逻辑简单清晰,任何人看一遍都能明白是怎么回事。出了问题也很好排查。
当然,这个算法也有它的局限性:
- 匹配逻辑比较简单:只是简单的字符串包含匹配,没有语义理解。比如"西红柿"和"番茄"就匹配不上。
- 没有考虑权重:所有食材的权重都是一样的。但实际上,主食材和辅料的重要性是不同的。
- 推荐结果单一:每次只推荐一道菜。如果能推荐多道菜供用户选择,体验会更好。
这些局限性,在接入真实的AI后都可以得到解决。真实的大语言模型,能够理解语义、考虑上下文、生成多样化的结果。但在Mock阶段,这样的算法已经足够支撑我们的开发和演示了。
3.2 菜谱展示与阅读体验优化
菜谱生成之后,如何展示给用户,也是一个很重要的问题。好的展示方式,能够让用户看得更清楚、学得更轻松。
在AI菜谱生成器中,我们将菜谱分为三个部分来展示:菜品信息、食材清单、烹饪步骤。
菜品信息区
菜品信息区位于菜谱的最上方,展示最核心的信息:菜名、难度、耗时。
菜名用大号加粗字体显示,是整个菜谱的视觉焦点。难度和耗时用小标签显示,放在菜名下方,让用户一眼就能了解这道菜的基本情况。
为什么要展示难度和耗时?因为这两个信息对于用户来说非常重要——新手可能不想做太难的菜,上班族可能没有太多时间做饭。把这些信息放在最显眼的位置,能够帮助用户快速判断这道菜是否适合自己。
食材清单区
食材清单区展示这道菜需要的所有食材。我们采用了标签式的展示方式——每种食材用一个圆角标签显示,标签之间用间距隔开,可以自动换行。
标签式展示的好处是: - 清晰直观:每种食材都是独立的标签,一目了然。
- 视觉效果好:橙色的文字配上浅橙色的背景,有层次感,也符合整体的配色风格。
- 易于阅读:用户可以快速扫一眼,就知道需要哪些食材。
除了食材名称,未来还可以在标签上显示更多信息,比如食材的用量、是否需要提前准备等。
烹饪步骤区
烹饪步骤是菜谱的核心,也是用户最关注的部分。我们采用了编号式的展示方式——每个步骤前面都有一个橙色的数字编号,步骤内容用常规字体显示。
编号式展示的好处是: - 顺序清晰:用户一眼就能看到步骤的顺序,不会搞混。
- 便于查找:用户可以很方便地说"我看到第3步了",或者直接跳到某一步。
- 节奏感强:编号和内容的组合,有一种"一步一步来"的节奏感,符合烹饪的流程感。
为了提升阅读体验,我们还做了以下优化:
行高优化:步骤文字设置了合适的行高(24vp),让文字之间有足够的呼吸感,读起来不费劲。长文本的阅读体验,行高是非常重要的。
间距优化:步骤之间设置了合适的间距(14vp),让每个步骤都有独立的视觉空间,不会挤在一起。
字号优化:步骤文字用了适中的字号(14fp),既保证了可读性,又不会太大导致一屏显示不了多少内容。
颜色优化:步骤文字用了深灰色(#444444),而不是纯黑色。深灰色在长时间阅读时更柔和,不容易造成视觉疲劳。
这些优化点,虽然单个看起来都不起眼,但组合在一起,就能够让用户的阅读体验提升一个档次。对于菜谱这样的内容消费型应用来说,阅读体验就是核心竞争力之一。
3.3 收藏与历史管理功能
好的菜谱,用户肯定想收藏起来,以后再做。做过的菜,用户也可能想回看一下步骤。因此,收藏和历史管理功能,是菜谱应用必不可少的一部分。
我们的收藏与历史管理功能,主要包括以下几个子功能:
收藏功能
用户在查看菜谱时,点击"收藏"按钮,就能将这道菜加入收藏。再次点击,则取消收藏。
收藏状态的切换,有明确的视觉反馈: - 未收藏时:显示"🤍 收藏",灰色文字,浅灰色背景。
- 已收藏时:显示"❤️ 已收藏",红色文字,浅红色背景。
同时,收藏/取消收藏成功后,还会弹出Toast提示,让用户明确知道操作成功了。
我的收藏
用户点击顶部的"我的收藏"按钮,就能进入收藏列表页面,查看所有收藏过的菜谱。
收藏列表采用卡片式布局,每张卡片展示一道菜的信息:菜名、食材、难度、耗时。每张卡片还有两个操作按钮:“查看"和"删除”。
点击"查看",会回到生成页面,展示这道菜的详细内容。点击"删除",则从收藏中移除这道菜。
如果收藏列表为空,会显示友好的空状态——一个星星图标,加上提示文字,引导用户去收藏菜谱。
历史记录
每次生成菜谱后,系统都会自动保存一条历史记录。历史记录展示在生成页面的下方,按时间倒序排列,最新的在最上面。
每条历史记录显示:菜谱名称、输入的食材、生成时间。每条记录还有一个"删除"按钮,用户可以删除不需要的历史记录。
历史记录的数量是有限制的——最多保存30条。当超过这个数量时,最早的记录会被自动挤掉。
为什么要限制数量?主要有两个考虑: - 性能考虑:太多的历史记录会占用更多的存储空间,也会影响列表的渲染性能。
- 产品考虑:太久远的历史记录,用户大概率不会再看了。保留最近的30条,已经足够用户回看了。
技术实现
在技术实现上,我们使用了鸿蒙提供的preferences轻量存储方案。preferences是鸿蒙ArkData包提供的一个轻量级数据存储接口,适合存储一些小批量的键值对数据。
具体的实现步骤:
- 获取preferences实例。
- 读取数据:根据key读取保存的JSON字符串,解析成数组。
- 写入数据:将数组序列化为JSON字符串,写入preferences,然后flush持久化。
收藏和历史记录,分别用不同的key存储:
- 收藏:favorite_recipes
- 历史:recipe_history
preferences的使用非常简单,API设计也很清晰。对于大多数应用的轻量存储需求来说,preferences完全能够满足。
交互细节
在交互设计上,我们也做了一些细节优化: - 收藏状态实时同步:在收藏列表删除了某道菜,回到生成页面时,如果当前正好是这道菜,收藏状态会自动更新。
- 历史记录自动保存:生成成功后自动添加历史,不需要用户手动操作。
- 删除操作便捷:每条记录都有删除按钮,不需要进入详情页删除。
- 空状态友好:没有收藏或历史时,显示友好的空状态,而不是一片空白。
这些细节,共同构成了一个好用的收藏与历史管理功能。
3.4 食材输入体验优化
食材输入,是用户使用AI菜谱生成器的第一步。这一步的体验好不好,直接影响着用户的第一印象。
在食材输入的设计上,我们做了以下几个优化:
多种分隔符支持
用户输入食材时,可能用各种分隔符——逗号、顿号、空格,甚至换行。我们的输入解析支持多种分隔符,无论用户用什么方式分隔,都能正确解析。
这是一个很小的细节,但能够大大降低用户的学习成本。用户不需要去想"我应该用什么分隔符",按照自己的习惯输入就好。
占位符提示
输入框的占位符,不仅提示了用户要输入什么,还给了一个示例:“请输入你有的食材,用逗号或空格分隔\n例如:番茄、鸡蛋、青椒”。
这个示例很重要。很多用户看到示例,就知道该怎么输入了,不需要额外的说明。
多行输入
我们用的是TextArea组件,支持多行输入。这样,用户输入的食材比较多时,也能完整地看到自己输入了什么,不会因为只有一行而被截断。
输入框的高度设置为100vp,大约能显示4-5行。对于大多数用户来说,这个高度足够了。如果用户输入的内容特别多,TextArea也支持滚动。
即时响应
用户输入的内容,会实时保存到状态变量中。用户输入完直接点生成按钮就行,不需要额外的确认步骤。
这是声明式UI的优势——数据驱动视图,状态变了,UI自动更新。
输入校验
点击生成按钮时,会先检查用户是否输入了内容。如果输入框是空的,会弹出Toast提示"请输入食材",不会执行生成操作。
这样的校验,能够避免无效的生成操作,也能给用户明确的反馈。
未来可以优化的方向
虽然当前的输入体验已经不错了,但还有很多可以优化的空间: - 语音输入:支持语音输入食材,用户直接说"我有番茄、鸡蛋、青椒",自动识别成文字。
- 图像识别:用摄像头拍一张冰箱的照片,AI自动识别里面有什么食材。
- 食材联想:输入时自动联想食材名称,比如输入"土",自动联想"土豆"、"土豆丝"等。
- 常用食材快捷输入:提供一些常用食材的快捷标签,点击就能添加。
- 历史输入记录:保存用户之前输入过的食材组合,一键复用。
这些优化,都能够进一步提升输入体验,让用户用起来更方便、更高效。
食材输入,虽然只是应用的一个小功能,但它是用户的"第一触点"。把第一步的体验做好,用户才会有继续使用下去的意愿。
第四章 鸿蒙PC端适配实践
4.1 响应式布局设计思路
鸿蒙PC的屏幕尺寸,和手机、平板有很大的不同。传统的移动端应用,如果直接搬到PC上,往往会出现"两边空荡荡"、"内容被拉伸"等问题。因此,做好PC端的响应式适配,是非常重要的。
在AI菜谱生成器中,我们采用了"移动端优先,渐进增强"的响应式设计思路。也就是说,我们先保证移动端的体验,然后在此基础上,针对PC端的大屏幕做优化。
为什么选择这种思路?主要有两个原因:
第一,移动端是基础。鸿蒙生态的主力设备依然是手机,大多数用户还是在手机上使用应用。因此,移动端的体验必须优先保证。
第二,渐进增强更高效。从移动端的布局出发,向PC端扩展,比从PC端的布局向移动端压缩要容易得多。而且,这种方式能够保证应用在所有设备上都有不错的体验,不会出现"移动端没法用"的情况。
具体到AI菜谱生成器的布局,我们可以从以下几个方面进行PC端适配:
宽度适配
内容区域设置最大宽度限制,在PC端不会无限拉伸。当屏幕宽度超过最大宽度时,内容区域居中显示,两边留出空白。
为什么要这样做?因为对于阅读来说,每行的字数是有最佳范围的。一般认为,中文每行60-80个字是比较舒适的阅读宽度。太宽了,用户的眼睛需要来回移动,容易疲劳;太窄了,又会频繁换行,打断阅读的连贯性。
对于菜谱应用来说,宽度适中尤其重要。步骤文字太宽,读起来会很累;食材标签太宽,又会显得稀疏。设置一个合理的最大宽度,能够保证在大屏幕上也有良好的阅读体验。
高度适配
菜谱展示区的高度,可以根据屏幕高度动态调整。在手机上,高度可能有限,需要滚动查看;在PC上,高度可以增加,让用户一屏能看到更多内容。
当然,在当前的实现中,菜谱展示区是自适应高度的——内容有多高,区域就有多高。这在内容不太长的时候是没问题的。但如果菜谱的步骤很多,页面就会变得很长,需要滚动很多。
在PC端,可以考虑将布局改为左右分栏,左边是输入和控制区,右边是菜谱展示区。这样,菜谱展示区的高度可以占满屏幕,用户不需要滚动页面,只需要在区域内滚动即可。
多列布局
在PC端的大屏幕上,可以考虑将布局从单列改为多列。比如:
- 左列:食材输入、生成按钮、历史记录
- 右列:菜谱展示(食材清单、烹饪步骤)
这样可以充分利用横向空间,让用户不用频繁滚动页面,操作效率更高。
对于菜谱应用来说,多列布局是一个非常值得考虑的优化方向。用户可以一边调整食材、查看历史,一边实时看到菜谱内容,体验会流畅很多。
字体和间距优化
在PC端,用户离屏幕的距离通常比手机远一些。因此,可以适当增大字号和间距,保证内容的可读性。
当然,这个调整要适度。太大的字号和间距,会显得内容稀疏,一屏显示不了多少信息。需要找到一个平衡点。
卡片尺寸优化
在收藏列表中,PC端可以考虑用网格布局(Grid),而不是列表布局。一行显示多张卡片,充分利用横向空间。
网格布局在PC端很常见,也更符合桌面端的使用习惯。用户可以一眼看到更多的内容,查找起来更高效。
以上这些,都是PC端响应式适配的常见思路。具体采用哪些,需要根据应用的实际情况来决定。
对于AI菜谱生成器这样的应用来说,我们认为"最大宽度限制 + 多列布局"是性价比最高的适配方案。实现起来不算太复杂,但体验提升非常明显。
4.2 大屏交互优化
除了布局的适配,PC端的交互方式也和移动端有很大的不同。PC端有鼠标、有键盘,有更精确的操作方式,也有更多的快捷键可以利用。
在AI菜谱生成器的PC端适配中,我们可以从以下几个方面进行交互优化:
鼠标交互优化 - 悬停效果:给按钮、标签、列表项等可点击元素,添加鼠标悬停效果。比如,鼠标移上去时,背景色变深一点,或者出现一个阴影。这样能够给用户明确的"可点击"反馈。
- 指针样式:对于可点击的元素,鼠标指针应该变成手型。这是桌面端的基本交互规范。
- 右键菜单:可以考虑添加右键菜单,提供一些快捷操作。比如,在菜谱上右键,可以收藏、分享、打印等。
- hover提示:对于一些图标按钮或者缩写,可以添加hover提示(Tooltip),鼠标悬停时显示完整的说明。
键盘快捷键支持
键盘快捷键的支持,对于提升PC端用户的使用效率来说,是非常重要的。很多重度用户,都习惯用键盘操作,而不是频繁地移动鼠标。
对于AI菜谱生成器,可以考虑支持以下快捷键: - Enter生成:用户输入完食材后,按Enter键直接触发生成,不用再去点击按钮。这能够大大提升操作效率。
- Ctrl+S收藏:这是桌面端最经典的快捷键,几乎所有内容类应用都支持。
- Tab键切换:支持Tab键在输入框、按钮等元素之间切换焦点,让纯键盘操作成为可能。
- 方向键滚动:菜谱内容区域支持方向键滚动,这是文本阅读类应用的标配。
- 数字键跳转步骤:按数字键1-9,直接跳转到对应的步骤。
这些快捷键,虽然不是必须的,但能够显著提升应用的专业感和用户体验。一款真正优秀的鸿蒙PC应用,应该充分利用桌面端的交互优势,而不是简单地把移动端应用放大。
窗口大小变化适配
PC端的窗口是可以自由调整大小的。应用应该能够响应窗口大小的变化,动态调整布局。
比如: - 当窗口很窄时,自动切换回单列布局。
- 当窗口足够宽时,切换到多列布局。
- 设置一个合理的最小窗口宽度和高度,当窗口小于这个尺寸时,出现滚动条,而不是让布局错乱。
这种"流式响应"的布局,能够让应用在各种窗口尺寸下都有不错的体验。
多窗口协作
鸿蒙PC支持多窗口并行。AI菜谱生成器可以考虑支持多窗口协作的场景。
比如: - 用户可以一边开着菜谱生成器,一边开着笔记应用,把好用的菜谱记下来。
- 一边看菜谱,一边开着视频应用,跟着视频学做菜。
- 一边查菜谱,一边开着购物应用,购买需要的食材。
更进一步,可以利用鸿蒙的分布式能力,让菜谱生成器和其他应用之间能够交换数据。比如,从笔记应用中拖拽一段文字到菜谱生成器中,直接作为食材输入。
打印支持
很多人喜欢把菜谱打印出来,贴在厨房里,做饭的时候看着做。因此,打印支持对于菜谱应用来说,是一个很实用的功能。
在PC端,可以很方便地实现打印功能。用户点击"打印"按钮,就能把菜谱打印出来。
打印的时候,还可以做一些优化: - 打印样式优化:去掉不必要的UI元素(按钮、导航等),只打印核心内容。
- 排版优化:针对打印纸张的尺寸,优化菜谱的排版。
- 省墨模式:提供黑白打印模式,节省墨水。
打印功能,虽然不是高频功能,但对于有需要的用户来说,是非常有价值的。
以上这些,都是PC端交互优化的常见方向。当然,不需要一次性全部实现,可以根据优先级逐步添加。但在设计的时候,心中要有这些方向,为后续的扩展留好空间。
4.3 多设备协同能力探索
说到鸿蒙,就不能不提分布式能力和多设备协同。这是鸿蒙最核心的特色,也是鸿蒙应用区别于其他平台应用的关键所在。
对于AI菜谱生成器这样的美食工具来说,多设备协同能力有着巨大的想象空间。我们可以从以下几个方向进行探索:
跨设备数据同步 - 用户在手机上收藏的菜谱,自动同步到PC端和平板端。用户打开PC上的应用,就能看到手机上收藏的菜谱,随时查看。
- 这种同步应该是实时的、无缝的。用户不需要手动导出导入,也不需要等待,打开就能用。
- 技术上,可以利用鸿蒙的分布式数据管理能力,或者结合云端同步服务来实现。
想象一下这样的场景:你在公司午休时,用手机刷菜谱,看到一道喜欢的,收藏了起来。晚上回到家,打开PC上的菜谱应用,那道菜已经在收藏列表里了,你可以直接用大屏幕看着详细步骤,开始做饭。
这种无缝的体验,是全场景智慧生活的基本要求。
跨设备能力调用
每个设备都有自己擅长的能力。通过分布式技术,我们可以让应用调用其他设备的硬件能力,实现"1+1>2"的效果。
比如: - 图像识别:用手机的摄像头拍摄食材,AI自动识别是什么食材,结果直接同步到PC的菜谱应用中。PC的摄像头通常不如手机方便,用手机的摄像头来拍照,体验更好。
- 语音输入:做饭的时候手上可能沾着油,不方便操作手机或键盘。这时候,可以用智慧屏的语音助手,直接说"下一步"、“重复一遍”,语音控制菜谱的播放。
- 称重联动:连接智能厨房秤,称食材的时候,菜谱应用自动显示当前食材的标准用量,告诉用户多了还是少了。
- 烤箱联动:菜谱里需要烤的步骤,可以直接推送到智能烤箱,自动设置温度和时间。
这些跨设备的能力调用,能够让菜谱应用从"一个看菜谱的软件",变成"真正的厨房助手"。
跨端流转
用户在手机上正在看一道菜谱,这时他走到了厨房,想在平板上继续看。只需要轻轻一碰,手机上的菜谱就"流"到了平板上,接着刚才的进度继续。
反过来,用户在PC上查了半天菜谱,选好了要做的菜,要去厨房做饭了,也可以把菜谱"流"到手机或平板上,带着走。
这种"无缝流转"的体验,是鸿蒙分布式能力的典型应用,也是全场景智慧生活的核心体现。
对于菜谱应用来说,流转的不仅是页面,还有状态——看到第几步了、设置了什么参数、收藏了没有,这些状态都应该一起流转过去。
多屏协同烹饪
做饭的时候,一个屏幕可能不够用。利用鸿蒙的多屏协同能力,可以同时使用多个屏幕。
比如: - 手机放在手边,用来控制步骤、看时间。
- 平板放在面前,展示当前步骤的详细说明和图片。
- 智慧屏挂在墙上,播放整个菜谱的教学视频。
多屏配合,让用户不用在不同的页面之间来回切换,做饭的效率更高,体验更好。
家庭共享
美食是家庭的纽带。菜谱应用也可以支持家庭共享功能。
比如: - 家庭成员共享一个菜谱库,大家收藏的菜谱都能看到。
- 妈妈在手机上选好了今天的菜谱,自动同步到爸爸和孩子的设备上。
- 家庭菜单投票:周末做什么菜,全家一起投票决定。
这种家庭共享的功能,能够大大增加应用的社交属性和用户粘性。
这些多设备协同的场景,听起来很美好,但实现起来也确实有一定的技术门槛。它需要开发者对鸿蒙的分布式技术有深入的理解,也需要对产品场景有清晰的把握。
但无论如何,这都是鸿蒙应用的发展方向。未来的鸿蒙应用,不应该是一个个孤立的"手机应用"或"PC应用",而应该是能够在全场景设备间无缝流转的"超级应用"。
对于AI菜谱生成器这样的工具型应用来说,越早布局多设备协同能力,就越能在未来的竞争中占据优势。
第五章 鸿蒙Flutter框架对比分析
5.1 技术栈对比
谈到鸿蒙开发,就绕不开一个话题:鸿蒙原生ArkTS开发 vs 鸿蒙Flutter框架开发。这两种方案各有优劣,开发者该如何选择?这是很多团队在做技术选型时都会面临的问题。
在这一章中,我们就以AI菜谱生成器为例,从多个维度对这两种方案进行深入的对比分析。
首先,我们来看技术栈的对比。
鸿蒙原生ArkTS开发
- 语言:ArkTS。这是鸿蒙的官方开发语言,基于TypeScript扩展而来,增加了静态类型检查和一些鸿蒙特有的语法特性。对于有前端开发经验的人来说,上手比较容易。
- UI框架:ArkUI声明式开发范式。这是鸿蒙官方的UI框架,采用声明式的写法,组件化开发,性能优秀。ArkUI提供了丰富的基础组件,能够满足大多数应用的需求。
- 系统能力:能够直接调用鸿蒙系统的所有原生能力。无论是分布式能力、AI能力,还是各种系统服务,都可以无缝接入。这是原生开发最大的优势。
- 生态工具:DevEco Studio,鸿蒙官方的IDE,功能完善,调试方便。DevEco Studio基于IntelliJ平台开发,对于用惯了JetBrains系列IDE的开发者来说,会比较熟悉。
鸿蒙Flutter框架开发 - 语言:Dart。这是Flutter框架的官方语言,由Google开发,语法类似Java和JavaScript的混合体,学习成本不高。Dart是一种强类型语言,支持面向对象,也支持函数式编程。
- UI框架:Flutter Widget。Flutter有自己的一套UI组件库,包括Material Design风格和Cupertino风格。组件丰富,自定义能力强。Flutter的UI是自己绘制的,不依赖系统控件,因此跨平台一致性很好。
- 系统能力:需要通过插件的方式调用系统能力。对于常见的能力(比如网络、存储、相机等),社区已经有成熟的插件。但对于鸿蒙特有的一些能力(比如分布式能力),可能需要自己开发插件,或者等待社区支持。
- 生态工具:VS Code / Android Studio + Flutter插件。开发工具成熟,热重载功能体验很好。Flutter的工具链已经发展了很多年,非常成熟。
从技术栈的角度来看,两者各有特色:
ArkTS的优势在于原生。它是鸿蒙的"亲儿子",与系统的结合最紧密,能够发挥出鸿蒙的全部能力。而且,随着鸿蒙生态的发展,ArkTS的重要性只会越来越高。
Flutter的优势在于跨平台。用Flutter开发的应用,可以同时运行在Android、iOS、鸿蒙、Web、桌面等多个平台上。对于需要多端发布的团队来说,Flutter能够大大节省开发成本。
5.2 开发效率对比
开发效率,是技术选型时非常重要的一个考量因素。我们从几个方面来对比一下:
学习曲线 - 如果你之前有前端开发经验(特别是TypeScript/React/Vue),那么ArkTS的学习曲线会比较平缓。声明式UI的思想是相通的,很多概念可以直接迁移。ArkTS的语法和TypeScript非常接近,前端开发者几乎可以无缝切换。
- 如果你之前有移动端开发经验(特别是Flutter/React Native),那么Flutter的学习曲线会更平缓。Dart语言也比较容易上手,对于有Java或JavaScript基础的人来说,学起来很快。
- 总体来说,两者的学习成本都不算高。对于有经验的开发者来说,大概一两周就能上手做项目。
开发速度 - Flutter的热重载(Hot Reload)功能非常强大,修改代码后几乎是立即看到效果,开发体验非常流畅。这是Flutter最受开发者称赞的特性之一。
- ArkTS的预览功能也在不断完善,DevEco Studio提供了实时预览的能力。但在热重载的速度和稳定性上,目前Flutter还是略胜一筹。
- 不过,ArkTS有一个优势——它的组件库和系统风格是统一的。你不需要花太多时间去定制UI样式,默认的组件就能做出符合鸿蒙设计规范的界面。这在一定程度上能够节省UI开发的时间。
代码复用 - Flutter的代码复用率非常高。一套代码,可以编译到多个平台。对于需要同时支持Android、iOS、鸿蒙的项目来说,Flutter能够节省大量的开发和维护成本。
- ArkTS的代码复用主要体现在鸿蒙设备内部——手机、平板、PC、智慧屏等,都可以用同一套代码。但如果要支持Android和iOS,就不行了。
调试体验 - 两者的调试工具都比较完善。Flutter有DevTools,ArkTS有DevEco Studio的调试器。基本的断点调试、日志查看、性能分析等功能都有。
- 对于原生能力的调试,ArkTS会更方便一些,毕竟是原生的。而Flutter如果涉及到原生插件的调试,会麻烦一些。
生态资源 - Flutter的生态非常成熟,各种第三方库、组件、教程都很多。遇到问题,很容易在网上找到解决方案。
- ArkTS的生态还在快速发展中。基础的能力官方都有提供,但一些更细分的领域,可能需要自己造轮子,或者等待社区完善。
总体来说,在开发效率这个维度上,Flutter略占优势。特别是对于需要多端发布的项目,Flutter的代码复用优势非常明显。但如果只针对鸿蒙平台,ArkTS的开发效率也不低,而且在系统能力的调用上更加顺畅。
5.3 性能表现对比
性能,是移动端开发永恒的话题。我们来对比一下两种方案的性能表现。
渲染性能 - Flutter有自己的渲染引擎(Skia/Impeller),UI的绘制不依赖系统控件,渲染性能非常稳定。而且Flutter的动画性能很好,能够轻松实现60fps的流畅动画。由于是自己绘制,Flutter的UI一致性很好,在不同平台上的表现基本一致。
- ArkUI的渲染性能也很优秀。作为鸿蒙的原生UI框架,它经过了系统级的优化,渲染效率很高。特别是对于列表、长文本等常见场景,ArkUI的表现非常出色。而且,作为原生框架,ArkUI与系统的结合更紧密,能够更好地利用系统资源。
- 总体来说,两者的渲染性能都属于第一梯队,普通用户很难感知到差异。在大多数场景下,都能达到流畅的体验。
启动速度 - 原生应用的启动速度通常会更快一些。ArkTS应用作为鸿蒙原生应用,启动速度应该会略快于Flutter应用。因为Flutter应用需要先启动Flutter引擎,再加载Dart代码,这个过程需要一些时间。
- 不过,Flutter的启动速度也在不断优化。对于普通用户来说,这点差异可能并不明显。特别是对于菜谱这样的工具型应用,启动速度的差异对用户体验的影响不大。
内存占用 - Flutter应用因为要携带渲染引擎,安装包体积和运行时内存占用通常会比原生应用大一些。这是跨平台框架的通病——为了跨平台,需要自带一套"运行环境"。
- ArkTS应用作为原生应用,内存占用会更轻量一些。它直接使用系统的渲染能力,不需要额外的渲染引擎。
- 对于AI菜谱生成器这样的轻量应用来说,这点差异可能影响不大。但对于内存敏感的场景,或者需要同时运行很多应用的场景,原生方案会更有优势。
长列表性能 - 长列表是很多应用都会遇到的性能场景。在这方面,两者都有不错的表现。
- ArkUI的List组件有很好的回收机制,长列表滚动流畅。
- Flutter的ListView也有成熟的回收机制,性能同样优秀。
- 对于菜谱应用来说,收藏列表、历史列表都不会太长,所以长列表性能不是大问题。但如果是做菜谱大全这样的应用,有几千几万道菜,就需要关注长列表的性能了。
功耗表现 - 原生应用通常在功耗控制上会更好一些。因为与系统结合更紧密,能够更好地利用系统的功耗优化机制。
- Flutter应用由于有自己的渲染引擎,在某些场景下可能功耗会稍高一些。不过Flutter团队也在持续优化功耗表现。
- 对于菜谱这样的工具型应用,功耗不是核心问题。用户不会长时间连续使用,功耗的差异感知不明显。
总体来说,在性能这个维度上,ArkTS原生方案略占优势。毕竟是原生的,与系统的结合更紧密,资源占用更低。但Flutter的性能也完全够用,对于大多数应用来说,都不会成为瓶颈。
5.4 生态成熟度对比
生态,是决定一个技术方案能否长久发展的关键因素。我们从几个方面来看一下两者的生态情况。
组件库 - Flutter的组件库非常丰富。除了官方的Material和Cupertino组件库,社区还有大量的第三方UI组件库。几乎你能想到的UI效果,都能找到现成的实现。从简单的按钮、卡片,到复杂的图表、动画,应有尽有。
- ArkUI的组件库也在快速发展中。官方提供的基础组件已经比较完善,能够满足大多数应用的需求。常用的按钮、输入框、列表、滚动等组件都有。但在高级组件、定制化组件方面,目前还不如Flutter丰富。
第三方库 - Flutter的第三方生态非常成熟。从网络请求、状态管理、数据存储,到图片加载、动画、图表、支付、分享,各种功能的库都有,而且质量普遍不错。Pub.dev上有数十万的包可供选择。
- ArkTS的生态还在建设中。基础的能力(网络、存储等)官方都有提供,但一些更细分的领域,可能需要自己造轮子,或者等待社区完善。不过,随着鸿蒙生态的发展,这个差距正在快速缩小。
开发社区 - Flutter的社区非常活跃。全球有大量的开发者在使用和贡献Flutter。遇到问题,很容易在网上找到解决方案。Stack Overflow、GitHub、Medium等平台上都有大量的Flutter相关内容。
- ArkTS的社区正在快速成长中。随着鸿蒙生态的发展,越来越多的开发者加入进来。国内的社区尤其活跃,相关的教程、文章、开源项目越来越多。华为官方也在大力推动社区建设。
学习资源 - Flutter已经发展了很多年,学习资源非常丰富。官方文档、书籍、视频教程、博客文章,应有尽有。无论是入门还是进阶,都能找到合适的学习资料。
- ArkTS的学习资源也在快速增加。官方文档比较完善,是最权威的学习资料。社区的教程、案例也越来越多。但总体来说,学习资源的丰富程度还不如Flutter。
就业市场 - Flutter已经发展了很多年,市场上有不少Flutter的岗位需求。特别是在中小公司和创业公司,Flutter因为其跨平台的优势,比较受欢迎。
- ArkTS是一个新兴的技术方向。随着鸿蒙生态的爆发,对ArkTS开发者的需求正在快速增长。目前来看,这是一个有潜力的赛道,人才缺口比较大。特别是在国内市场,鸿蒙的发展势头很猛,相关的岗位需求会越来越多。
总体来说,在生态成熟度这个维度上,Flutter目前占据明显优势。毕竟Flutter已经发展了很多年,生态非常成熟。但ArkTS的生态也在快速追赶中,特别是在国内市场,随着鸿蒙的普及,ArkTS的生态会越来越完善。
5.5 如何选择适合的技术方案
说了这么多,那么到底该如何选择呢?
其实,没有绝对的"最好"的方案,只有"最适合"的方案。选择哪种技术方案,要根据你的具体情况来决定。
选择鸿蒙原生ArkTS的场景: - 深度绑定鸿蒙生态:你的应用主要面向鸿蒙平台,想要充分利用鸿蒙的特色能力(比如分布式能力、AI能力等)。如果你的应用的核心竞争力就是鸿蒙的分布式能力,那么原生开发几乎是必然选择。
- 追求极致性能和体验:你想要做一款深度融入鸿蒙生态的应用,追求最好的性能和最原生的体验。原生应用在性能、流畅度、系统集成度上,通常还是会比跨平台方案好一些。
- 团队有前端背景:你的团队有前端开发背景,学习ArkTS的成本比较低。如果团队本来就熟悉TypeScript和React/Vue,那么转ArkTS会非常快。
- 看好鸿蒙未来:你看好鸿蒙的未来,想要在这个生态中提前布局。如果鸿蒙生态发展得好,早期进入的开发者会有很大的优势。
选择鸿蒙Flutter框架的场景: - 多平台发布需求:你的应用需要同时支持多个平台(Android、iOS、鸿蒙等),想要用一套代码搞定。Flutter的跨平台优势,在这种场景下体现得最明显。
- 团队已有Flutter经验:你的团队已经有Flutter开发经验,不想重新学习一套新技术。技术的积累和传承,对于团队来说很重要。
- 大量自定义UI:你的应用需要大量的自定义UI效果,Flutter的渲染引擎更适合做这些。Flutter的自定义能力非常强,几乎可以实现任何你想要的UI效果。
- 依赖成熟生态:你需要用到大量的第三方库,而Flutter的生态更加成熟。如果你的应用功能很复杂,需要依赖很多第三方库,那么Flutter会更省心一些。
对于AI菜谱生成器这样的应用来说: - 如果只是做鸿蒙平台的版本,那么原生ArkTS是更好的选择。它能够提供更好的性能、更原生的体验,也能更好地融入鸿蒙生态。而且,菜谱应用可以很好地结合鸿蒙的分布式能力,做很多有特色的功能。
- 如果需要同时发布到多个平台,那么Flutter会更合适。一套代码,多端运行,能够大大节省开发和维护成本。对于创业团队来说,这一点很重要。
当然,这也不是绝对的。很多时候,技术选型还要考虑团队情况、项目周期、预算等因素。最重要的是,根据自己的实际情况,做出最适合的选择。
最后,我想说的是:技术方案只是工具,产品和用户体验才是核心。无论是ArkTS还是Flutter,都只是实现产品的手段。只要能够做出用户喜欢的产品,就是好的技术方案。
第六章 离线Mock方案与网络接入设计
6.1 Mock数据设计思路
在AI应用的开发过程中,我们经常会遇到这样的问题:后端API还没开发好,或者AI模型还没训练完,前端开发怎么办?总不能一直等着吧?
这时候,离线Mock方案就派上用场了。所谓Mock,就是模拟真实的数据和接口,让前端能够独立开发和调试,不需要依赖后端。
在AI菜谱生成器的开发中,我们就采用了完整的离线Mock方案。这让我们在没有真实AI接口的情况下,也能够完成整个应用的开发、调试和演示。
那么,Mock数据应该如何设计呢?我们总结了以下几个要点:
真实性
Mock数据要尽可能真实,不能太随意。比如,番茄炒蛋的食材就应该是番茄、鸡蛋、葱花这些,步骤也应该是真实的烹饪步骤。只有Mock数据足够真实,开发出来的UI和交互才是有意义的。
在AI菜谱生成器中,我们精心挑选了8道经典家常菜作为Mock数据,包括:
- 素菜类:番茄炒蛋、青椒土豆丝、蒜蓉西兰花、酸辣土豆丝
- 荤菜类:红烧肉、宫保鸡丁、麻婆豆腐、可乐鸡翅
每道菜的食材和步骤,都是真实的菜谱,不是随便编的。用户在使用Mock版本时,也能获得不错的体验,甚至真的可以照着做出菜来。
多样性
Mock数据要有足够的多样性,不能太单一。如果所有菜谱都是同一种类型、同一种风格,用户很快就会觉得单调。
我们在选择Mock菜谱时,考虑了多样性: - 类型多样:有素菜也有荤菜,有家常菜也有稍微复杂一点的菜。
- 难度多样:有简单的(15分钟就能做好),也有中等难度的(需要一个小时)。
- 口味多样:有酸甜口味的(番茄炒蛋、可乐鸡翅),有麻辣口味的(麻婆豆腐、宫保鸡丁),有咸鲜口味的(红烧肉、蒜蓉西兰花)。
- 食材多样:涵盖了常见的各种食材——蔬菜、肉类、豆制品等。
这样的多样性,能够让用户在使用Mock版本时,也能感受到应用的丰富性。
完整性
Mock数据要覆盖所有的业务场景。不仅要有正常的情况,还要考虑各种边界情况。
比如: - 食材少的菜谱(比如番茄炒蛋只有几种食材)和食材多的菜谱(比如红烧肉有很多调料)都要有,测试不同长度的食材列表的展示效果。
- 步骤少的菜谱(比如4步)和步骤多的菜谱(比如7步)都要有,测试长文本和短文本的展示效果。
- 考虑各种异常情况:输入的食材都匹配不上怎么办?输入为空怎么办?这些都需要在Mock阶段就考虑到,并且有相应的处理逻辑。
可扩展性
Mock数据的结构要易于扩展。后续添加新的菜谱,或者增加新的字段,都不应该需要大量修改代码。
我们采用的Recipe接口设计,就具有很好的可扩展性。添加新的菜谱,只需要在MOCK_RECIPES数组中增加一个对象即可,不需要修改其他代码。如果后续需要增加新的字段(比如图片、营养信息等),也只需要在Recipe接口中添加,然后在数据中填充即可。
做好Mock数据,不仅能够让前端开发独立进行,还有一个额外的好处——它能够帮助我们更好地理解产品和业务。在编写Mock数据的过程中,你会不断思考:真实的菜谱应该是什么样的?用户会关心哪些信息?这个功能到底有没有用?这些思考,能够让你对产品有更深的理解。
6.2 预留API接口设计
Mock只是暂时的,最终我们还是要接入真实的API。因此,在设计Mock方案时,就要考虑好后续的接入问题。最好的做法是:预留好API接口,让Mock和真实API的切换成本降到最低。
在AI菜谱生成器中,我们是这样做的:
首先,定义一个统一的服务接口——RecipeApiService。这个接口定义了菜谱生成服务的规范,对上层提供统一的接口。
interface RecipeApiService {
fetchRecipe(params: GenParams): Promise;
}
然后,提供一个实现类——RecipeApiServiceImpl。这个类实现了RecipeApiService接口。在Mock阶段,它的实现是返回Mock数据;接入真实API后,它的实现就是发起网络请求。
class RecipeApiServiceImpl implements RecipeApiService {
async fetchRecipe(params: GenParams): Promise {
// TODO: 接入真实后端API时在此处实现
return MOCK_RECIPES[0];
}
}
在业务逻辑中,通过接口类型来引用服务实例,而不是直接依赖具体的实现类。
private recipeApiService: RecipeApiService = new RecipeApiServiceImpl();
这样的设计,有以下几个好处:
关注点分离
网络请求的逻辑被封装在Service层,UI层不需要关心数据是怎么来的——是Mock的还是真实API的,对UI层来说都是一样的。UI层只需要调用接口,拿到数据,然后展示。
这种分层设计,能够让各层的职责更加清晰,代码更容易理解和维护。
易于切换
Mock和真实API的切换,只需要修改Service层的代码,不需要动UI层。这大大降低了切换的成本和风险。
当后端API开发好之后,前端只需要修改RecipeApiServiceImpl的实现,把Mock逻辑换成真实的网络请求即可。上层的业务代码和UI代码,一行都不用改。
易于测试
在测试时,可以很方便地用Mock Service来替代真实的Service,避免网络请求对测试的影响。
比如,在写单元测试的时候,可以注入一个Mock的Service实现,返回固定的测试数据。这样,测试就不会依赖网络环境,也不会因为网络波动而失败。
易于扩展
如果后续需要增加新的API接口,只需要在RecipeApiService接口中添加新的方法,然后在实现类中实现即可。接口的定义和实现是分离的,扩展起来很方便。
这种"面向接口编程"的思想,是非常重要的设计原则。它能够让你的代码更加灵活,更容易应对变化。
当然,对于AI菜谱生成器这样的简单应用,这样的设计可能显得有点"重"。但即使是小项目,养成良好的设计习惯也是好的。随着项目的迭代,代码会越来越复杂,这时候你会发现,前期的架构设计是多么重要。
6.3 真实AI接口接入指南
前面说了这么多Mock,那么当真实的AI接口准备好了,具体该如何接入呢?我们来梳理一下完整的接入步骤。
第一步:了解API文档
首先,你需要仔细阅读后端提供的API文档,搞清楚以下几个问题: - 接口地址是什么?
- 请求方式是什么(GET/POST)?
- 请求参数有哪些?分别是什么类型?
- 返回的数据格式是什么样的?
- 有没有鉴权要求(比如需要传token)?
- 接口的限流策略是什么?
- 接口的响应时间大概是多少?
这些问题不搞清楚,后面的开发就无从谈起。如果文档有不清楚的地方,一定要及时和后端同学沟通。
第二步:实现网络请求
在鸿蒙中,我们通常使用@kit.NetworkKit提供的http能力来进行网络请求。你需要: - 导入http模块。
- 创建http请求。
- 设置请求方法、URL、header、body等。
- 发送请求,获取响应。
- 解析响应数据。
具体的代码大致是这样的:
import { http } from ‘@kit.NetworkKit’;
class RecipeApiServiceImpl implements RecipeApiService {
async fetchRecipe(params: GenParams): Promise {
const url = ‘https://api.example.com/recipe/generate’;
const request = http.createHttp();
const response = await request.request(url, {
method: http.RequestMethod.POST,
header: {
'Content-Type': 'application/json',
'Authorization': 'Bearer xxx' // 如果需要鉴权
},
extraData: JSON.stringify(params)
});
if (response.responseCode === 200) {
const result = JSON.parse(response.result as string);
// 将返回的数据转换为Recipe格式
return this.convertToRecipe(result);
} else {
throw new Error(`请求失败,状态码:${response.responseCode}`);
}
}
private convertToRecipe(data: any): Recipe {
// 将后端返回的数据格式转换为前端的Recipe接口格式
return {
id: data.id,
name: data.name,
ingredients: data.ingredients,
steps: data.steps,
difficulty: data.difficulty,
time: data.time
};
}
}
当然,这只是一个最基本的示例。在实际项目中,你还需要考虑错误处理、超时设置、重试机制、请求取消等问题。
第三步:替换Mock逻辑
将generateRecipe方法中的Mock逻辑,替换为对recipeApiService.fetchRecipe的调用。同时,处理好异步逻辑和错误捕获。
需要注意的是,真实的API调用是异步的,需要用async/await或者Promise来处理。同时,要做好异常捕获,避免因为网络错误导致应用崩溃。
第四步:处理各种边界情况
接入真实API后,会遇到很多Mock阶段不会遇到的问题:
- 加载状态:网络请求需要时间,要给用户明确的加载反馈。比如,按钮文字变成"生成中…",按钮置灰,防止重复点击。
- 错误处理:网络请求可能失败,要处理各种错误情况(网络错误、服务器错误、参数错误等),并给用户友好的提示。不能让用户看到一堆看不懂的错误码。
- 超时处理:设置合理的超时时间,避免用户长时间等待。如果超时了,要给用户提示,并提供重试的选项。
- 重试机制:对于网络波动等临时性错误,可以考虑自动重试。但要注意重试的次数和间隔,避免给服务器造成太大压力。
- 限流处理:如果接口有限流,要做好相应的处理,避免触发限流后影响用户体验。比如,可以在前端做一些频率限制。
这些边界情况的处理,往往是决定应用质量的关键。很多应用在Demo阶段看起来很好,但一到真实环境就各种问题,就是因为边界情况没有处理好。
第五步:性能优化
接入真实API后,还可以做一些性能方面的优化: - 预加载:在用户输入的过程中,就提前发起请求,减少用户等待时间。但要注意不要太频繁,避免浪费流量和服务器资源。
- 缓存策略:对于相同的食材输入,可以考虑缓存结果,避免重复请求。这样既能提升响应速度,又能节省服务器成本。
- 流式输出:如果AI接口支持流式输出(SSE),可以实现打字机效果,让用户能够边生成边阅读,大大提升体验。特别是对于比较长的菜谱步骤,流式输出能够让用户感觉"更快"。
- 图片懒加载:如果菜谱有图片,要做懒加载,避免一次性加载太多图片导致卡顿。
总之,接入真实API不是简单地"把Mock换掉"就行了,它涉及到很多细节的处理。只有把这些细节都做好,才能给用户提供流畅、稳定的使用体验。
6.4 离线优先的架构思考
聊完了Mock和API接入,我们来聊一个更深层次的话题:离线优先(Offline-First)的架构思想。
什么是离线优先?简单来说,就是应用的设计以离线可用为基础,网络连接只是增强能力。也就是说,即使没有网络,应用也能正常使用;有网络的时候,再同步数据、增强功能。
为什么要提倡离线优先?主要有以下几个原因:
第一,网络不是永远都有的。用户可能在地铁上、在电梯里、在信号不好的地方,这时候如果应用完全不能用,体验就太差了。特别是在厨房这样的场景,网络信号可能不好,如果菜谱应用因为没网就打不开,那用户体验会非常糟糕。
第二,离线体验更流畅。本地操作的响应速度,永远比网络请求快。如果应用的核心功能都能在本地完成,用户的使用体验会非常流畅。点击就有反应,不需要转圈等待。
第三,节省流量和成本。减少网络请求,不仅节省用户的流量,也能降低服务器的成本。对于用户量大的应用来说,这可能是一笔不小的开支。
对于AI菜谱生成器这样的应用来说,离线优先的架构是否合适呢?
我们认为,部分合适。
AI菜谱生成器的核心功能——智能生成菜谱,是依赖AI能力的。而强大的AI能力,目前主要还是在云端。所以,核心的生成功能,很难完全离线化。
但是,应用的其他功能,完全可以做到离线优先: - 收藏的菜谱:保存在本地,离线也能查看。用户收藏的菜谱,应该随时都能看,不管有没有网。
- 历史记录:保存在本地,离线也能回看。
- 基础菜谱库:内置一些基础的菜谱,离线也能查看和使用。就像我们现在的Mock数据一样。
- 设置项:应用的各种设置,保存在本地。
然后,在有网络的时候,可以提供增强功能: - AI生成:调用云端的大模型,生成更多、更智能的菜谱推荐。
- 云端同步:将用户的收藏、历史记录同步到云端,多设备共享。
- 更多菜谱:从云端下载更多、更丰富的菜谱库。
- 高级功能:比如营养分析、菜单规划、购物清单等高级功能。
这种"核心功能离线可用,增强功能在线提供"的模式,是一种非常务实的离线优先策略。它既保证了应用的基本可用性,又充分利用了网络的优势。
在AI菜谱生成器的设计中,我们其实已经不自觉地采用了这种思路。我们的Mock菜谱、本地存储、收藏管理,都是离线可用的;而真实的AI生成能力,则是需要联网的增强功能。
这种架构思想,值得每一个鸿蒙开发者思考。在网络越来越发达的今天,我们反而应该回过头来,重视离线体验。因为,真正好的应用,应该是"随时随地都能用"的。
而且,鸿蒙的分布式能力,与离线优先的思想是相辅相成的。分布式能力保证了数据在多设备间的同步,而离线优先保证了每个设备都能独立工作。两者结合,就能实现"在线同步,离线可用"的最佳体验。
第七章 性能优化与用户体验提升
7.1 渲染性能优化
性能,是用户体验的基石。一个再好看、功能再强大的应用,如果卡顿、掉帧,用户也不会喜欢。因此,性能优化是开发过程中非常重要的一环。
在鸿蒙ArkUI开发中,渲染性能是我们最需要关注的性能点之一。我们来聊一聊常见的渲染性能优化技巧。
合理使用组件
ArkUI提供了丰富的组件,但并不是越多越好。在实现同样功能的情况下,应该尽量使用更轻量的组件。
比如,能用Text组件实现的,就不要用Button组件;能用Row/Column实现的布局,就不要用更复杂的Flex组件。组件越简单,渲染的开销就越小。
在AI菜谱生成器中,我们的食材标签用的是Text组件+背景色+圆角,而不是用Button组件。因为标签只需要展示,不需要复杂的交互,用Text就够了。
另外,要注意避免组件的过度嵌套。组件的嵌套层级越深,渲染时的计算量就越大。应该尽量保持扁平的组件结构。
当然,这也不是绝对的。为了代码的可读性和可维护性,适当的嵌套是必要的。我们要避免的是"为了嵌套而嵌套"的无意义层级。
合理使用状态管理
状态的变化会触发组件的重新渲染。因此,合理地管理状态,减少不必要的重新渲染,是性能优化的重要手段。
具体来说:
- 状态的粒度要合适。不要把所有状态都放在一个大对象里,那样一个属性变了,整个对象都要更新,所有用到这个对象的组件都要重新渲染。
- 只在必要的组件中使用状态。如果一个状态只在某个子组件中用到,就把状态定义在子组件里,不要提到父组件。
- 对于不需要触发UI更新的数据,不要用@State等响应式装饰器,用普通变量就行。
在AI菜谱生成器中,我们的状态都是比较细粒度的——输入的食材、当前的菜谱、收藏列表等,都是独立的状态变量。这样,某个状态变化时,只会影响用到它的那部分UI,不会造成大面积的重新渲染。
列表优化
列表是最容易出现性能问题的场景之一。对于长列表,一定要注意以下几点: - 使用List组件,而不是Column + ForEach。List组件有内置的回收机制,能够大大提升长列表的性能。
- 给列表项设置合理的高度。如果列表项的高度是固定的,最好显式指定,这样List组件能够更准确地计算布局,减少测量开销。
- 避免在列表项中做复杂的计算。列表项的渲染速度直接影响滚动的流畅度,复杂的计算应该提前做好,缓存起来。
在AI菜谱生成器中,收藏列表和历史列表都用的是List组件。虽然目前数据量不大,性能问题不明显,但这是一个好的习惯。随着数据量的增加,List组件的优势会越来越明显。
图片优化
图片也是影响性能的常见因素。对于图片的使用,有以下几个建议: - 图片大小要合适。不要加载比显示区域大很多的图片,那样既浪费内存,又浪费带宽。
- 合理使用图片缓存。对于重复使用的图片,要利用好缓存机制,避免重复加载。
- 避免在滚动过程中加载图片。可以等滚动停止后再加载,或者使用懒加载的方式。
目前的AI菜谱生成器还没有图片,所以这方面的压力不大。但如果后续添加了菜品图片,就要注意图片性能的优化了。
减少动画的使用
适当的动画能够提升用户体验,但过多的动画则会影响性能。特别是复杂的、同时运行的动画,很容易造成掉帧。
在使用动画时,要注意: - 优先使用系统提供的动画组件和属性,这些通常经过了优化。
- 避免在动画中做复杂的计算。
- 对于不重要的动画,可以考虑降低帧率或者简化效果。
在AI菜谱生成器中,我们没有使用太多复杂的动画,主要是一些基础的状态切换。这样既能保证体验,又不会有性能问题。
当然,对于AI菜谱生成器这样的应用来说,性能问题可能并不突出。因为它的UI不复杂,也没有长列表、大量图片等容易出问题的场景。但了解这些优化技巧,在遇到复杂场景时,就能够做到心中有数。
7.2 内存管理优化
除了渲染性能,内存管理也是性能优化的重要方面。内存占用过高,可能会导致应用被系统杀死,或者影响设备的整体流畅度。
在鸿蒙ArkTS开发中,我们可以从以下几个方面来优化内存使用:
及时释放不需要的资源
这是内存管理最基本的原则。对于不再需要的资源,要及时释放。
比如: - 定时器(setTimeout/setInterval),在组件销毁时要及时清除。
- 事件监听器,在不需要时要及时取消。
- 大对象,在不用时可以设置为null,帮助垃圾回收。
在AI菜谱生成器中,我们使用了setTimeout来模拟生成延迟。虽然这个延迟时间不长(1.2秒),但如果组件在延迟期间被销毁了,定时器还是会继续执行,这就可能造成内存泄漏。虽然在这个单页面应用中不太会遇到这种情况,但养成良好的习惯总是好的。
避免内存泄漏
内存泄漏是指那些已经不需要的内存,却没有被释放,导致内存占用越来越高。内存泄漏是应用性能下降的常见原因。
常见的内存泄漏场景有: - 未清除的定时器和事件监听器。
- 闭包引用了大对象,导致对象无法被回收。
- 全局变量持有了大对象的引用。
- 缓存无限增长,没有淘汰策略。
要避免内存泄漏,首先要有内存管理的意识,知道哪些操作可能导致泄漏。其次,要善用开发工具,定期检查内存使用情况,发现问题及时排查。
在AI菜谱生成器中,我们的收藏列表和历史记录都有数量限制——收藏没有明确限制,但历史记录最多30条。这除了是产品层面的考虑,也是内存管理的考虑。如果没有限制,用户用了几年,存了几千条记录,内存占用就会很高。
优化图片内存
图片是内存占用大户。一张高清图片,解码后可能会占用好几兆甚至几十兆的内存。如果应用中有大量图片,内存压力会很大。
优化图片内存的方法有: - 使用合适尺寸的图片。不要加载比显示区域大很多的图片。
- 对图片进行压缩。
- 合理使用图片缓存,设置缓存上限。
- 对于不在可视区域内的图片,可以考虑回收。
目前AI菜谱生成器还没有图片,所以这方面的压力不大。但后续如果添加了图片功能,就要特别注意。
优化数据存储
如果应用中有大量的数据需要保存在内存中,也要注意内存的使用。
比如,在AI菜谱生成器中,我们的历史记录最多只保留30条。这除了是产品层面的考虑,也是内存管理的考虑——保存太多记录,会占用更多内存。
对于更复杂的数据场景,可以考虑使用分页加载、懒加载等方式,避免一次性加载所有数据到内存中。
比如,如果做一个菜谱大全应用,有几千几万道菜,就不能一次性都加载到内存里。应该用分页的方式,每次只加载一页的数据。
使用性能工具进行分析
最后,要善用开发工具提供的性能分析功能。DevEco Studio提供了内存分析、CPU分析等工具,能够帮助你找到性能瓶颈和内存泄漏点。
不要凭感觉去优化,要用数据说话。通过工具找到真正的性能瓶颈,再有针对性地进行优化,才能事半功倍。
很多开发者容易陷入"过早优化"的误区——还没搞清楚性能瓶颈在哪里,就开始各种优化,结果花了很多时间,性能却没什么提升。正确的做法是:先用工具分析,找到真正的瓶颈,然后集中精力优化那个点。
7.3 交互体验优化
性能是"硬指标",而交互体验则是"软实力"。有时候,即使性能很好,如果交互设计得不好,用户也会觉得"不好用"。反过来,有时候性能虽然不是顶尖,但通过巧妙的交互设计,能够让用户觉得"很快"、“很流畅”。
我们来聊一聊交互体验优化的一些常见思路。
及时反馈
用户的每一个操作,都应该有及时的反馈。这是交互设计的基本原则。
比如: - 点击按钮,按钮要有按压效果,让用户知道"我点到了"。
- 发起网络请求,要有加载状态,让用户知道"正在处理"。
- 操作成功,要有成功提示,让用户知道"搞定了"。
- 操作失败,要有错误提示,让用户知道"出问题了",以及为什么出问题、该怎么办。
在AI菜谱生成器中,我们做了这些反馈设计: - 生成菜谱时,按钮文字变成"生成中…",并且按钮置灰,防止重复点击。
- 收藏/取消收藏成功后,弹出Toast提示。
- 输入为空时点击生成,弹出提示。
- 收藏状态有明确的视觉变化(心形图标和文字颜色变化)。
这些反馈虽然都是小细节,但能够让用户对应用的状态有清晰的感知,大大提升使用的安全感。
减少等待感
等待,是用户最讨厌的事情之一。但有些等待是不可避免的——比如网络请求、AI生成。这时候,我们能做的,就是减少用户的等待感。
怎么减少等待感?有几个常用的技巧:
第一,用有趣的加载动画。一个设计精美的加载动画,能够让等待变得不那么无聊。比如,可以用一个做饭的小动画,既贴合应用主题,又能缓解等待的焦虑。
第二,给出进度提示。如果能够知道大致的进度,就给用户一个进度条。即使不知道准确的进度,也可以给一些阶段性的提示,比如"正在分析食材…“、“正在匹配菜谱…”、“正在生成步骤…”,让用户知道"还在正常进行中”。
第三,利用等待时间做其他事情。比如,在生成菜谱的同时,可以展示一些烹饪小技巧,或者推荐几道热门菜谱。这样,用户就不会觉得是在"干等"。
第四,乐观更新。对于一些成功率很高的操作,可以先假设成功,更新UI,然后后台再去真正执行。如果失败了,再回滚并提示用户。这样能够给用户"秒级响应"的感觉。
比如,收藏操作,其实可以先在UI上显示"已收藏",然后后台再去写本地存储。因为本地存储的失败率极低,几乎不会失败。这样用户会觉得"响应很快"。
简化操作路径
好的交互,应该是"不用想就能用"的。用户不需要学习,不需要看帮助文档,拿到手就知道该怎么操作。
要做到这一点,就要尽量简化操作路径: - 核心功能要放在最显眼的位置,用户一眼就能看到。
- 操作步骤要尽量少,能一步完成的就不要分两步。
- 交互方式要符合用户的习惯,不要搞"反人类"的设计。
在AI菜谱生成器中,核心操作(输入食材、点击生成)都集中在页面的上半部分,用户打开应用就能看到,操作非常直接。输入食材后,点一下按钮就能生成菜谱,非常简单。
提供撤销和恢复
人都会犯错,用户也不例外。好的应用,应该允许用户犯错,并且能够方便地撤销错误操作。
比如: - 删除了收藏的菜谱,能不能恢复?
- 清空了内容,能不能撤销?
- 生成了新菜谱,能不能回到上一个?
提供撤销和恢复功能,能够让用户更有安全感,更敢去尝试各种操作。否则,用户会因为怕犯错而不敢探索,这会大大限制应用的使用深度。
在AI菜谱生成器中,目前我们还没有提供撤销功能——这是一个可以改进的点。比如,删除收藏时,可以加一个"撤销"的选项;清空内容时,可以加一个确认弹窗。
减少用户的输入成本
能让用户少输入的,就尽量让用户少输入。能让用户选择的,就不要让用户手动输入。
比如,食材输入,如果能提供常用食材的快捷标签,用户点一下就能添加,就比手动输入方便多了。再比如,可以保存用户常用的食材组合,一键复用。
减少用户的输入成本,不仅能够提升效率,也能减少输入错误。
交互体验的优化,是一个永无止境的过程。它需要你站在用户的角度,去思考每一个细节,去感受每一次操作。只有真正把用户放在心上,才能做出体验优秀的产品。
7.4 无障碍设计考量
聊完了性能和交互,我们来聊一个经常被忽略,但非常重要的话题——无障碍设计。
什么是无障碍设计?简单来说,就是让产品能够被更多人使用,包括那些有身体障碍的用户——比如视力障碍、听力障碍、运动障碍等。
很多开发者可能会觉得:“我的应用用户量不大,不需要考虑无障碍吧?“或者"无障碍设计太麻烦了,投入产出比不高。”
但实际上,无障碍设计不仅是社会责任的体现,也能提升所有用户的体验。而且,随着相关法律法规的完善,无障碍设计正在逐渐成为产品的"必选项”。
在鸿蒙开发中,我们可以从以下几个方面来考虑无障碍设计:
视觉无障碍
对于视力障碍的用户,主要依靠屏幕阅读器(比如鸿蒙的读屏功能)来使用应用。因此,我们需要: - 给所有重要的UI元素设置合适的内容描述(accessibility label)。比如,一个"生成"按钮,它的描述应该是"根据输入的食材生成菜谱",这样屏幕阅读器才能准确地告诉用户这个按钮是做什么的。
- 图片和图标要有文字说明。不能只有图标没有文字,那样视力障碍的用户不知道是什么意思。
- 保证足够的颜色对比度。对于色弱或者视力不好的用户,颜色对比度太低会导致看不清文字。
在AI菜谱生成器中,我们的按钮都有文字标签,这对于无障碍来说是友好的。但如果有纯图标按钮,就需要特别注意设置无障碍描述。
另外,我们的主色调是橙色,文字是深灰色,背景是白色,颜色对比度还是比较高的,可读性不错。
听觉无障碍
对于听力障碍的用户,应用中的所有声音提示,都应该有对应的视觉替代。比如: - 有新消息时,除了声音提示,还要有横幅或者角标提示。
- 操作成功的提示音,也要配合Toast或者其他视觉提示。
好在AI菜谱生成器主要是视觉和文字交互,没有太多声音相关的内容,这方面的压力不大。
运动无障碍
对于运动障碍的用户,可能无法精确地点击小按钮,或者无法完成复杂的手势操作。因此,我们需要: - 可点击的元素要有足够大的尺寸。鸿蒙的设计规范中,建议可点击区域不小于48x48vp。
- 点击区域之间要有足够的间距,避免误触。
- 提供替代的交互方式。比如,除了点击,还支持键盘操作、语音操作等。
在AI菜谱生成器中,我们的主按钮高度是50vp,符合无障碍的建议尺寸。其他按钮的高度也都在32vp以上,虽然不是特别大,但对于普通用户来说够用了。如果要做得更完善,可以考虑把所有可点击元素的尺寸都提到48vp以上。
认知无障碍
对于有认知障碍的用户,应用的设计要尽量简单、清晰、一致: - 界面布局要清晰,功能分区要明确。
- 用词要简单易懂,避免专业术语和复杂的句子。
- 交互流程要简单,步骤不要太多。
- 保持设计的一致性,同样的功能在不同的地方要有同样的表现。
AI菜谱生成器的界面比较简单,功能也不复杂,这对于认知无障碍来说是友好的。用词也比较通俗,都是日常用语,用户容易理解。
无障碍设计的好处
很多人觉得无障碍设计是"为少数人服务",投入产出比不高。但实际上,无障碍设计的受益者是所有人。
比如: - 足够大的按钮,不仅对运动障碍用户友好,对所有人来说都更容易点击。
- 足够高的对比度,不仅对视力障碍用户友好,在阳光下也能看得更清楚。
- 简单清晰的界面,不仅对认知障碍用户友好,所有用户都能更快上手。
- 语音操作,不仅对障碍用户有用,在手上没空的时候也很好用。
所以说,无障碍设计不是"额外的负担",而是"提升整体体验的投资"。
作为开发者,我们应该从一开始就有无障碍的意识,把它融入到日常的开发中。这不仅是为了合规,更是为了让我们的产品,能够被更多人使用,给更多人带来价值。
第八章 踩坑实录与最佳实践
8.1 开发过程中的常见问题
任何项目的开发,都不会是一帆风顺的。在AI菜谱生成器的开发过程中,我们也遇到了各种各样的问题。这一章,我们就来聊聊那些"踩过的坑",以及从中总结出的最佳实践。
坑一:TextArea的高度问题
刚开始做食材输入框的时候,我们想让输入框的高度能够根据内容自动调整——内容少的时候矮一点,内容多了自动变高。
但是,ArkUI的TextArea组件,默认是固定高度的。如果不设置高度,它会占据父组件的所有剩余空间。如果设置了固定高度,内容多了就会出现滚动条,而不是自动增高。
怎么办呢?我们尝试了几种方案:
- 方案一:监听内容变化,动态计算高度。但是TextArea的行数不好精确计算,特别是有中文换行的时候。
- 方案二:用Text组件模拟输入框。但这样又失去了TextArea的编辑能力。
- 方案三:干脆就用固定高度,反正食材输入不需要写太长。
最后,我们选择了方案三——设置一个固定的高度(100vp)。因为对于食材输入来说,输入个七八种食材就差不多了,100vp的高度足够。固定高度虽然不那么"智能",但简单、稳定、可预期。
这个坑告诉我们:有时候,最简单的方案反而是最好的方案。不要为了追求"完美"而把问题复杂化,能够满足需求的方案就是好方案。
坑二:长文本的性能问题
菜谱的步骤展示,我们一开始用的是普通的Column + Text。当步骤比较少的时候,没问题。但如果菜谱的步骤很多,或者用户连续生成了好几道菜,页面就开始有点卡了。
为什么会这样?因为如果所有内容都直接渲染,不管有没有在可视区域内,内容越长,性能就越差。
解决方案是什么呢?对于特别长的内容,可以考虑用Scroll包裹,或者用List来展示每个步骤。这样,渲染的开销会小很多。
不过,在AI菜谱生成器中,由于每道菜的步骤都不会太多(最多七八步),所以性能问题还不明显。但如果后续要做更长的内容,就要注意这个问题了。
这个坑告诉我们:对于长文本、长列表,一定要考虑滚动和回收。不要让所有内容都一次性渲染,那样性能会很差。
坑三:preferences的数据大小限制
在做收藏功能的时候,我们一开始没有限制收藏的数量。用户想存多少就存多少。
后来我们意识到,preferences是轻量级存储,不适合存大量数据。如果用户收藏了很多道菜,每道菜又有很多步骤,数据量会越来越大,可能会影响preferences的读写性能,甚至超出它的能力范围。
于是,我们给历史记录加上了数量限制(最多30条)。收藏虽然没有明确限制,但也建议在产品设计上考虑这个问题。
这个坑告诉我们:要了解你使用的技术方案的边界。每种技术都有它适用的场景和不适用的场景,不要超出它的能力范围去使用。
坑四:JSON序列化与类型丢失
从preferences中读取数据时,我们需要把JSON字符串解析成Recipe数组。一开始,我们直接用JSON.parse,然后就当作Recipe来用了。
这样做有什么问题吗?在JavaScript/TypeScript中,这样做很常见。但在ArkTS中,由于有严格的类型检查,这样做可能会有问题——JSON.parse返回的是any类型(或者说unknown类型),直接赋值给具体类型的数组,可能会有类型安全问题。
当然,在我们这个场景中,因为数据是我们自己存进去的,格式是可控的,所以问题不大。但这提醒我们:在ArkTS中,要更加重视类型安全。对于从外部读取的数据,最好做一下类型校验,或者显式地进行类型转换。
坑五:匹配算法的边界情况
在做食材匹配算法的时候,我们一开始没有考虑边界情况。比如: - 用户输入的食材都匹配不上怎么办?
- 用户输入为空怎么办?
- 多道菜的匹配度相同怎么办?
这些边界情况,如果不提前考虑到,就可能导致bug。比如,如果所有菜的匹配度都是0,那么就会返回第一道菜,这显然不太合理。
后来,我们加上了输入校验(输入为空时提示),也对匹配算法的边界情况做了处理。
这个坑告诉我们:开发的时候要多考虑边界情况。正常流程往往不容易出问题,出问题的往往是各种边界情况。
以上这些,只是开发过程中遇到的几个比较有代表性的问题。实际开发中,遇到的小问题还有很多。但正是这些问题,让我们对鸿蒙开发有了更深的理解。
8.2 调试技巧与工具
开发过程中,调试是必不可少的环节。掌握好调试技巧,能够大大提升开发效率。我们来分享几个鸿蒙开发中常用的调试技巧。
善用日志输出
这是最基础、也是最常用的调试方法。在关键的位置加上日志,观察变量的值、函数的执行情况,能够帮助你快速定位问题。
在鸿蒙中,你可以使用console.log来输出日志。DevEco Studio的LogCat窗口能够看到应用的所有日志输出。
建议: - 日志信息要清晰,最好带上所在的函数和关键变量的值。
- 不同级别的信息用不同的日志方法(log/info/warn/error)。
- 调试完后,记得清理掉不必要的日志,或者用开关控制。
使用断点调试
比日志更高级的调试方式是断点调试。在DevEco Studio中,你可以给代码打断点,然后以调试模式运行应用。当执行到断点处时,应用会暂停,你可以查看当前的调用栈、所有变量的值,还可以单步执行代码。
断点调试适合排查比较复杂的问题——比如逻辑错误、状态异常等。通过单步执行,你可以清晰地看到代码的执行流程,找到问题出在哪一步。
建议: - 学会使用条件断点。当满足某个条件时才暂停,这样不用一次次手动跳过。
- 学会使用日志断点。不暂停程序,只输出日志。这对于排查线上问题很有用。
使用预览器
ArkUI提供了实时预览功能。在DevEco Studio中,你可以一边写代码,一边看到UI的实时效果。这对于UI开发来说,效率提升非常大。
建议: - 多使用预览器来调整UI,不要每次都跑到真机或者模拟器上去看。
- 可以同时预览不同设备尺寸下的效果,快速验证响应式布局。
使用性能分析工具
当遇到性能问题时,不要凭感觉去猜,要用工具去分析。DevEco Studio提供了性能分析工具,可以查看CPU占用、内存使用、渲染帧率等信息。
通过性能分析工具,你可以找到性能瓶颈在哪里——是渲染太慢?还是计算太多?还是内存泄漏?找到问题后,再有针对性地去优化。
真机调试 vs 模拟器调试
最后,聊一下真机和模拟器的选择。
模拟器的优点是方便、启动快、不需要额外的设备。对于大多数UI开发和逻辑调试来说,模拟器就够用了。
但是,模拟器和真机还是有差异的——性能差异、系统版本差异、某些硬件能力的差异。因此,在发布之前,一定要在真机上测试一下,确保没有问题。
特别是涉及到性能、系统能力、硬件相关的功能,必须用真机测试。模拟器上跑得好,不代表真机上也跑得好。
8.3 代码组织与可维护性
代码写出来是给人看的,顺便给机器执行。可维护性,是衡量代码质量的重要标准。特别是对于团队项目,或者需要长期迭代的项目,代码的可维护性非常重要。
我们来聊一聊,在鸿蒙ArkTS开发中,如何提升代码的可维护性。
保持代码的清晰和简洁
这是最基本的要求。代码要写得清晰易懂,让别人(或者几个月后的你自己)能够快速看懂。
具体来说: - 变量和函数的命名要有意义,能够"见名知意"。不要用a、b、c这样的名字,也不要用过于缩写的名字。
- 函数的职责要单一,一个函数只做一件事。如果一个函数太长,或者做了太多事情,就考虑把它拆分成几个小函数。
- 适当添加注释。对于复杂的逻辑、特殊的处理、容易误解的地方,加上注释说明。但不要写"废话注释"。
保持代码的一致性
同一个项目中,代码的风格要保持一致。包括命名风格、缩进、换行、括号的位置等等。
一致的代码风格,能够让阅读者更快地理解代码,减少因为风格不同造成的误解。
如果是团队项目,最好制定一套代码规范,所有人都遵守。可以使用Lint工具来自动检查和修复代码风格问题。
合理组织文件结构
随着项目越来越大,所有代码都写在一个文件里肯定是不行的。需要合理地组织文件结构。
常见的组织方式有: - 按功能模块分:每个功能一个文件夹,里面包含这个功能的所有文件。
- 按类型分:components文件夹放组件,pages文件夹放页面,utils文件夹放工具函数,services文件夹放服务层代码。
对于AI菜谱生成器这样的小项目,所有代码都写在Index.ets里问题不大。但如果项目变大了,就要考虑拆分文件了。
遵循分层架构
我们在前面提到过分层架构的设计思想。遵循分层架构,能够让代码的职责更清晰,更容易维护。
UI层、服务层、数据层,各干各的事,不要混在一起。当需要修改某个功能时,你知道该去哪一层找;当需要替换某个实现时,只需要改一层,不会影响其他层。
写好错误处理
错误处理,是代码中很重要,但经常被忽略的部分。很多人写代码,只考虑"正常流程",不考虑"异常情况"。这样的代码,健壮性很差,一出问题就崩。
好的代码,应该考虑到各种可能的异常情况,并且有相应的处理逻辑。比如: - 网络请求失败了怎么办?
- 用户输入了非法数据怎么办?
- 读取本地存储失败了怎么办?
- 调用系统API出错了怎么办?
对于这些异常情况,至少要做到:不崩溃、有提示、可恢复。
写好单元测试
单元测试,是保证代码质量的重要手段。通过单元测试,你可以确保每个函数、每个模块都按照预期工作。
当然,对于UI代码,单元测试不是那么好写。但对于业务逻辑层、工具函数层,完全可以也应该写单元测试。
单元测试还有一个额外的好处:它能够倒逼你写出更好的代码。因为难测试的代码,往往不是好代码。
代码的可维护性,是一个很大的话题。以上只是几点最基本的建议。更重要的是,要有"代码质量"的意识,在写每一行代码的时候,都想一想:这样写好不好?以后会不会看不懂?能不能更好?
8.4 给鸿蒙开发者的建议
最后,结合AI菜谱生成器这个项目的开发经验,我们给广大鸿蒙开发者提几点建议。
建议一:打好基础,从官方文档开始
鸿蒙开发的资料,最权威、最全面的,还是官方文档。很多开发者喜欢到处找教程、找博客,但其实最好的学习资料就是官方文档。
建议大家从官方文档入手,系统地学习ArkTS语言、ArkUI框架、系统能力等。把基础打牢了,后面的学习才能事半功倍。
官方文档不仅有API说明,还有很多最佳实践和设计指南。这些都是官方经验的总结,非常有价值。
建议二:多动手,多实践
编程是一门实践的学问。光看文档、看教程是不够的,一定要多动手写代码。
找一个自己感兴趣的小项目(比如AI菜谱生成器这样的工具应用),从零开始做一遍。在做的过程中,你会遇到各种各样的问题,解决这些问题的过程,就是你成长的过程。
不要怕犯错,也不要怕写得不好。写得多了,自然就越来越好。
建议三:关注官方动态,跟上生态发展
鸿蒙生态还在快速发展中,新的能力、新的特性、新的工具,都在不断推出。
建议大家多关注鸿蒙的官方动态——开发者大会、版本更新、技术文章等。及时了解最新的技术和趋势,才能跟上生态的发展。
特别是鸿蒙PC、鸿蒙平板这些新的设备形态,会带来很多新的机会。提前了解和学习,才能抢占先机。
建议四:积极参与社区,多交流分享
一个人学习,进步是有限的。多和其他开发者交流,能够开阔眼界,学到很多东西。
鸿蒙的社区正在快速成长中,有很多优秀的开发者在分享自己的经验和心得。你可以多看看别人的文章和项目,也可以自己写一写、分享一下。
教,是最好的学。当你试着把自己学到的东西讲给别人听的时候,你会发现自己理解得更深刻了。
建议五:保持开放的心态,不要有"技术宗教"
最后,也是最重要的一点:保持开放的心态。
不要觉得"原生就是最好的",也不要觉得"跨平台就是王道"。每种技术都有它的优势和劣势,都有它适用的场景。
作为开发者,我们的目标是解决问题、创造价值,而不是捍卫某种技术。选择最适合当前场景的技术方案,才是正确的做法。
鸿蒙原生开发也好,鸿蒙Flutter框架也好,都只是工具。重要的是,你能用这些工具做出什么样的产品。
保持学习的热情,保持开放的心态,不断提升自己的能力。这样,无论技术怎么变,你都能立于不败之地。
第九章 未来展望与扩展方向
9.1 AI能力的深度升级
AI菜谱生成器,目前还只是一个比较基础的版本。未来,它还有很大的升级空间。而AI能力的深度升级,无疑是最重要的方向之一。
我们可以从以下几个方面来升级AI能力:
更强的生成模型
目前的Mock版本,用的是固定的菜谱库。即使接入真实API后,用的可能也是通用的大语言模型。未来,我们可以训练专门的美食生成模型,让生成的菜谱质量更高、更专业、更符合中国人的口味。
比如,可以针对不同菜系训练专门的模型——川菜模型、粤菜模型、鲁菜模型等。这样,每个菜系的生成效果都会更地道。
还可以训练专门的"家常菜"模型,专门生成适合家庭制作的、简单好吃的菜谱。毕竟,大多数用户用菜谱应用,都是为了做家常菜。
更丰富的控制参数
目前,用户只能输入食材。未来,可以提供更丰富的控制参数,让用户能够更精细地控制生成的菜谱。比如:
- 人数/分量:几个人吃,自动调整食材的用量。
- 口味偏好:清淡、麻辣、酸甜、咸鲜等,根据口味调整菜谱。
- 难度选择:新手入门、进阶、大厨级别,不同难度的菜谱。
- 时间限制:只有30分钟,推荐能在30分钟内做好的菜。
- 菜系选择:川菜、粤菜、鲁菜、家常菜等。
- 饮食禁忌:不吃辣、不吃海鲜、素食、低糖低脂等,自动避开禁忌食材。
参数越丰富,用户的参与感就越强,生成的菜谱也就越符合用户的期望。
更智能的生成逻辑
目前的生成,只是简单的"根据食材推荐菜谱"。未来,可以实现更智能的生成逻辑: - 营养均衡搭配:不仅推荐一道菜,还可以推荐一整套菜单,保证营养均衡。
- 食材利用率最大化:根据用户现有的食材,推荐能够最大化利用这些食材的菜单,减少浪费。
- 步骤智能调整:根据用户的烹饪水平,自动调整步骤的详细程度。新手就写详细点,老手就写简洁点。
- 厨具适配:考虑用户有什么厨具,推荐适合的菜谱。比如,只有电饭煲的话,就推荐电饭煲能做的菜。
这些更智能的功能,能够大大提升应用的价值和用户粘性。
多模态生成
未来,AI菜谱生成器不一定只生成文字。还可以结合多模态AI能力,生成更多形式的内容: - AI配图:为每道菜生成精美的菜品图片。
- AI视频:生成烹饪步骤的教学视频。
- AI语音:把菜谱朗读出来,或者生成语音教程。
- AR展示:用AR技术,在厨房中虚拟展示烹饪步骤。
从文字到图文,再到音视频、AR,AI菜谱生成器可以进化成一个"AI美食教学平台"。
图像识别输入
除了文字输入,还可以支持图像识别输入。用户拍一张冰箱的照片,或者拍一下手里的食材,AI自动识别有哪些食材,然后推荐菜谱。
这种"拍照识别食材"的功能,能够大大降低用户的输入成本,让应用用起来更方便。
当然,这些能力的升级,需要强大的AI技术作为支撑。但随着AI技术的快速发展,这些都不是遥不可及的。
9.2 多端协同与分布式能力
我们在前面的章节中提到过多设备协同。这是鸿蒙应用的特色,也是未来的重要发展方向。
对于AI菜谱生成器来说,多端协同可以从以下几个方向深入:
无缝流转体验
这是最基础的分布式能力应用。用户在手机上看了一半的菜谱,坐到PC前,一碰就能流转到PC上继续看。做饭的时候,又可以流转到平板或智慧屏上,跟着学。
这种"拿起哪台设备,就在哪台设备上继续"的体验,是全场景智慧生活的核心体现。
要实现无缝流转,需要用到鸿蒙的分布式能力调度和分布式数据管理。应用的状态和数据,能够在设备间无缝传递——看到第几步、收藏了没有、设置了什么参数,这些都要一起流转过去。
跨设备能力调用
更进一步,应用可以调用其他设备的硬件能力,来增强自己的功能。
比如: - 图像识别:用手机的摄像头拍摄食材,AI自动识别是什么食材,结果直接显示在PC的菜谱应用中。PC的摄像头通常不如手机方便,用手机的摄像头来拍照,体验更好。
- 语音控制:做饭的时候手上沾着油,不方便操作。这时候,可以用智慧屏的语音助手,直接说"下一步"、“重复一遍”、“计时5分钟”,语音控制菜谱的播放。
- 称重联动:连接智能厨房秤,称食材的时候,菜谱应用自动显示当前食材的标准用量,告诉用户多了还是少了。还可以自动记录实际用了多少,计算实际的营养摄入。
- 厨具联动:菜谱里需要烤的步骤,可以直接推送到智能烤箱,自动设置温度和时间。需要煮的步骤,可以推送到智能电饭煲。
每个设备都有自己擅长的能力,通过分布式技术,让这些能力能够被其他设备调用,实现"1+1>2"的效果。
多屏协同烹饪
对于做饭这件事来说,多屏协作是非常有吸引力的功能。
比如: - 手机放在手边,用来控制步骤、看时间、设置计时器。
- 平板放在面前,展示当前步骤的详细说明和图片。
- 智慧屏挂在墙上,播放整个菜谱的教学视频。
- 智能秤显示当前食材的重量。
多屏配合,让用户不用在不同的页面之间来回切换,做饭的效率更高,体验更好。
家庭共享与协作
美食是家庭的纽带。菜谱应用也可以支持家庭共享功能。
比如: - 家庭成员共享一个菜谱库,大家收藏的菜谱都能看到。
- 家庭菜单:每周吃什么,全家一起规划。
- 购物清单:根据菜单自动生成购物清单,全家人都能看到,谁有空谁就买。
- 家庭排行榜:谁做的菜最好吃,大家投票评选。
家庭共享功能,能够大大增加应用的社交属性和用户粘性。美食本身就是社交的润滑剂,围绕家庭做文章,能够产生很多有趣的玩法。
多端协同和分布式能力,是鸿蒙应用的"独门绝技"。把这方面做好了,就能做出其他平台做不出来的体验,形成自己的核心竞争力。
9.3 社区生态与内容建设
一个菜谱应用的核心竞争力,除了AI能力,就是内容了。菜谱越丰富、质量越高,对用户的吸引力就越大。
因此,内容建设和社区生态,是AI菜谱生成器未来发展的重要方向。
我们可以从以下几个方向,来建设内容和社区:
UGC菜谱社区
目前的菜谱都是官方提供的。未来,可以开放UGC(用户生成内容)功能,让用户也能上传自己的菜谱。
比如: - 用户可以创建和发布自己的菜谱。
- 用户可以给菜谱配图、拍视频、写心得。
- 用户可以给别人的菜谱点赞、评论、收藏。
- 可以关注喜欢的美食达人,看他们的最新菜谱。
UGC能够大大丰富菜谱的数量和多样性,也能增加用户的参与感和粘性。
菜谱分类与标签体系
随着菜谱越来越多,需要有完善的分类和标签体系,方便用户查找。
比如: - 按菜系分:川菜、粤菜、鲁菜、家常菜、西餐、日料等。
- 按食材分:猪肉、牛肉、鸡肉、鱼类、蔬菜等。
- 按场景分:早餐、午餐、晚餐、夜宵、下午茶、节日大餐等。
- 按难度分:新手入门、进阶、大厨级别。
- 按功能分:减肥餐、健身餐、儿童餐、老人餐、月子餐等。
完善的分类体系,能够让用户更快地找到自己想要的菜谱,也能让内容组织得更有条理。
排行榜与推荐系统
好的内容需要被更多人看到。可以通过排行榜和推荐系统,让优质内容脱颖而出。
比如: - 热门排行榜:最近最受欢迎的菜谱。
- 新品推荐:最新发布的优质菜谱。
- 个性化推荐:根据用户的口味偏好和历史记录,推荐可能喜欢的菜谱。
- 编辑精选:编辑推荐的优质菜谱。
好的推荐系统,能够大大提升用户的发现效率,也能让优质内容创作者获得更多曝光。
美食社区与话题
除了菜谱,还可以建设美食社区,让用户可以分享美食生活。
比如: - 话题讨论:#今天吃什么#、#厨房小白的逆袭#、#一人食#等话题。
- 晒图分享:用户晒自己做的菜,分享心得。
- 问答专区:用户可以提问,比如"番茄炒蛋怎么才能不酸",其他用户或专家回答。
- 美食活动:定期举办美食活动,比如"一周家常菜挑战"、“我的拿手菜"等。
社区能够大大提升用户的活跃度和停留时长,让应用从"工具"变成"平台”。
达人与创作者生态
对于优质的内容创作者,可以给予扶持和激励,建立达人生态。
比如: - 认证美食达人,给予特殊标识。
- 提供流量扶持,让更多人看到他们的内容。
- 提供变现渠道,比如付费课程、电商带货等。
- 举办创作者活动,帮助创作者成长。
有了优质的创作者,才有优质的内容。建立良好的创作者生态,是内容平台长期发展的基础。
当然,社区和内容的建设,不是一朝一夕的事情。它需要长期的投入和运营。但这是一个值得努力的方向——内容和社区,是菜谱应用最深的护城河。
9.4 商业化探索
最后,我们来聊一个很现实的话题:商业化。
任何一款产品,要想长期发展,都需要有可持续的商业模式。AI菜谱生成器也不例外。
美食类应用的商业化路径其实很清晰,我们可以从以下几个方向来探索:
食材电商
这是菜谱应用最直接的商业化方式。推荐菜谱的同时,推荐对应的食材,用户可以直接下单购买。
比如: - 每道菜的食材清单旁边,都有"一键购买"按钮。
- 根据用户的菜单,自动生成购物清单,一键下单所有食材。
- 推荐优质的食材品牌,做精选电商。
- 结合本地生鲜配送,实现"看着菜谱,食材送到家"。
食材电商的变现效率很高,因为用户正在看菜谱的时候,购买意愿是最强的。这时候推荐食材,转化率会比较高。
厨房用品带货
除了食材,厨房用品也是一个很大的市场。
比如: - 菜谱中用到的锅、刀、厨具等,可以推荐购买。
- 做"厨房好物"推荐,分享好用的厨房工具。
- 推荐小家电,比如空气炸锅、电饭煲、烤箱等。
- 可以做测评和对比,帮助用户选择。
厨房用品的客单价通常比食材高,利润空间也更大。
付费内容与课程
对于有更高需求的用户,可以提供付费内容。
比如: - 高级菜谱:更专业、更精致的菜谱,需要付费查看。
- 烹饪课程:从入门到精通的系列课程,视频教学。
- 营养师咨询:一对一的营养咨询,定制饮食方案。
- 会员订阅:包月/包年会员,享受所有付费内容。
付费内容的好处是毛利率高,而且能够筛选出高价值用户。
本地生活服务
结合地理位置,提供本地生活服务。
比如: - 推荐附近的菜市场、生鲜店。
- 推荐附近的美食餐厅。
- 推荐附近的烹饪培训班。
- 外卖推荐:不想做饭的时候,推荐附近的外卖。
本地生活服务可以通过佣金或广告的方式变现。
品牌广告
当用户量足够大的时候,品牌广告也是一个重要的收入来源。
比如: - 开屏广告。
- 首页banner广告。
- 菜谱详情页的品牌植入。
- 搜索结果的品牌推广。
广告变现的好处是门槛低,不需要用户付费也能有收入。但缺点是会影响用户体验,而且收入相对有限。
B端合作
除了面向C端用户,还可以探索B端的合作机会。
比如: - 为生鲜电商平台提供菜谱推荐能力。
- 为智能厨房设备提供内容和算法支持。
- 为餐饮企业提供菜品研发、菜单设计服务。
- 为健康管理平台提供营养计算和饮食建议能力。
B端合作的客单价高,收入稳定。但需要有较强的商务和定制开发能力。
商业化的道路有很多条,没有哪一条是绝对正确的。需要根据产品的特点、用户的情况、市场的环境,来选择最适合的方式。
但无论选择哪种方式,有一点是共通的:产品本身要有价值。只有真正为用户创造了价值,商业化才是水到渠成的事情。
结语
写到这里,这篇关于AI菜谱生成器的技术长文,就要告一段落了。
回顾全文,我们从鸿蒙PC生态的大背景出发,深入拆解了AI菜谱生成器的每一个技术细节——从项目架构、数据结构,到核心功能的实现原理;从鸿蒙PC端的适配实践,到鸿蒙Flutter框架的对比分析;从离线Mock方案的设计,到性能优化和用户体验提升;从开发过程中的踩坑实录,到未来的发展方向和商业化探索。
我们希望,通过这样一个完整的实战案例,能够让你对鸿蒙原生开发有一个更全面、更深入的理解。
AI菜谱生成器,只是一个很小的应用。但它所涉及的技术点、所体现的设计思想,却具有普遍的参考价值。无论是做什么类型的鸿蒙应用,你都能从本文中找到一些可以借鉴的东西。
当然,由于篇幅和水平的限制,本文不可能涵盖鸿蒙开发的所有方面。还有很多技术点,我们没有深入展开;还有很多优化的空间,等待着你去探索。
鸿蒙生态,正处在一个快速发展的黄金时期。每天都有新的能力推出,每天都有新的机会出现。对于开发者来说,这是一个充满机遇的时代。
我们相信,随着鸿蒙PC的普及,随着鸿蒙生态的不断完善,会有越来越多的优秀应用涌现出来。而美食工具类应用,凭借其高频性、实用性和社交属性,必将在鸿蒙生态中占据重要的一席之地。
美食,是中国人生活中最温暖的部分。而技术,正在让这份温暖变得更加触手可及。AI菜谱生成器,就是技术与美食的一次美好相遇。它用智能的方式,帮助人们解决"今天吃什么"的千古难题,让更多人能够享受做饭的乐趣,享受美食的快乐。
最后,想送给所有鸿蒙开发者一句话:保持热爱,保持好奇,保持行动。
热爱这个正在蓬勃发展的生态,好奇那些未知的技术和可能性,然后,行动起来——去写代码,去做产品,去创造价值。
鸿蒙的未来,需要每一个开发者的参与。而AI菜谱生成器的故事,也还远远没有结束。
愿我们都能在鸿蒙的世界里,烹饪出属于自己的精彩人生。
参考资料:
- 鸿蒙开发者官方文档
- ArkUI开发指南
- 鸿蒙分布式能力介绍
- Flutter for HarmonyOS 相关资料
- 鸿蒙PC适配最佳实践
- 鸿蒙应用设计规范
更多推荐


所有评论(0)