☰
鸿蒙OpenHarmony下RN图片懒加载完整实战与性能优化
2026/10/8 14:52:02 网站建设 项目流程

做 React Native for OpenHarmony(下面简称 RNOH)也有一段时间了,最直观的感受是:这玩意儿把前端那套跨端开发体验带到了鸿蒙生态里,但底层的渲染、内存、生命周期又和 Android/iOS 不完全一样。尤其是图片加载,如果直接把 Web 端的懒加载思路搬过来,在 RNOH 上经常会出现“不生效”或者“反而更卡”的怪现象。这篇文章我准备用一整个实战案例,把 LazyLoading 在 RNOH 下的完整实现思路、代码细节、性能对比、还有我踩过的坑都摊开聊一遍。如果你想在 OpenHarmony 设备上做长列表图片信息流,或者想解决 react native 启动白屏、图片一多就内存暴涨的问题,这篇文章应该能帮你节约好几个晚上的排查时间。

反正在我看来,图片懒加载从来不是“少加载几张图”那么简单,它直接关系到首屏渲染速度、滚动流畅度、内存占用,甚至能影响 OpenHarmony 设备上应用能否顺利通过 xts 认证(跑压力测试时内存峰值太难看会被打回来)。所以别急着写代码,先搞清楚 RNOH 的图片加载链路是怎么工作的。

1. 为什么要做图片懒加载:从鸿蒙原生到跨端的一致体验

1.1 图片加载在 RNOH 场景下的真实痛点

先说一个现象:我在 RK3568 开发板上跑一个 20 条数据的信息流,每张图 200KB,没用懒加载时,页面启动直接白屏 1.8 秒,之后快速滑动明显掉帧,系统内存峰值飙到 800MB 出头,再开别的应用直接被杀掉。这还是本地图片,如果是网络图片,情况更糟。

为什么会这样?首先,RNOH 的 Image 组件底层走的是 OpenHarmony 的图片解码框架,在列表初始化阶段,所有可见和不可见的 Image 都会一次性触发请求。哪怕你设置defaultSource占位,底层资源也已经开始占了。其次,OpenHarmony 上常见的设备内存比旗舰手机小不少,很多开发板只有 2GB RAM,系统可用内存可能就 1.2GB,一个图片列表就能把内存吃光。

所以懒加载不是“优化点”,而是“保命点”。它的核心思路很简单:只加载当前视口内(或者说即将进入视口)的图片,视口外的图片延迟到接近可见时再加载。这样首屏资源请求数量从“全部”变成“少数”,CPU/IO 压力大幅下降,内存自然稳下来。

1.2 懒加载的核心原理与收益

单独说原理,可能你会觉得抽象。我用生活化类比解释一下:懒加载就像餐厅后厨上菜,不是一次性把所有菜都做好摆着,而是根据客人的节奏一道一道上。客人还没点到的菜,后厨就算备好食材,也不开火。

在 RNOH 里实现懒加载,本质是回答三个问题:

  1. 如何知道图片是否进入视口?
  2. 进入视口后如何触发真实加载?
  3. 移出视口后是否要释放资源?

对应到技术方案上,常见的做法有两种:一是基于 FlatList 的onViewableItemsChanged回调,二是基于滚动事件的坐标计算。前者是 React Native 官方推荐的方式,因为 FlatList 内部已经有可视区域计算的逻辑,性能好且稳定;后者更自由,但需要自己处理节流和边界情况。

采用懒加载后,最直观的收益是首次渲染时间缩短。以我的实测为例,20 张图的信息流,懒加载后首屏只加载 4 张图,启动白屏时间从 1.8 秒降到 0.9 秒,内存峰值从 800MB 降到 350MB 左右。这个差异在真机上非常可感,尤其是低端设备。

1.3 RNOH 中图片加载链路差异

这里必须明确一个关键点:RNOH 并不是把 React Native 的 Image 直接翻译成 OpenHarmony 的 Image,而是通过 C++ 桥接层映射到 ArkUI 的Image组件。也就是说,图片解码、缓存、渲染都发生在 OpenHarmony 侧,而 JavaScript 层只管下发状态。

RNOH 的底层实现语言主要是 C++ 和 ArkTS,这一点早期困惑过我——因为 OpenHarmony 本身是用什么语言编写的这个问题网上答案五花八门,但实际你不需要关心全部,你只需要知道:RNOH 的运行时骨架是 C++,组件层和 ArkUI 通讯靠的是 NAPI。所以在图片加载这件事上,RNOH 的性能瓶颈往往不在 JS 层,而在原生解码和内存分配。这意味着做懒加载时,必须考虑“原生侧是否真的释放了资源”,而不是 JS 层把<Image>节点卸载就觉得万事大吉。

我见过不少开发者用条件渲染{visible && <Image />}来做懒加载,表面上看图片没渲染,但底层 RNOH 可能仍然持有这个组件对应的原生节点缓存,导致内存没有明显改善。真正有效的做法,是依赖 FlatList 的回收机制 + 控制 Image 的加载源,让原生侧认为“没有加载任务”。

基于这些背景,下面进入实操。

2. 上手实操:在 RNOH 项目中实现基础版图片懒加载

2.1 工程环境与依赖准备

我当前使用的环境是:OpenHarmony 4.0 Release(API 10),react-native 0.72.5(RNOH 社区适配版),开发框架用的是@react-native-oh/react-native-harmony。如果你用的是更高版本,API 名字可能略有变化,但核心思路一致。

工程初始化建议直接用 RNOH 社区的脚手架,手动集成容易踩坑。图片列表的数据结构我简化如下:

interface FeedItem { id: string; title: string; imageUrl: string; }

测试数据放在一个本地 JSON 里,网络图片我用了几个公网测试源,注意 OpenHarmony 应用需要申请网络权限,不然图片加载会直接失败并且报错很隐晦。在module.json5里加上:

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

这一步漏掉,你会看到Image一直显示占位图,但控制台没有任何明确的网络错误提示,我当初排查了很久。

2.2 基于 FlatList 的 onViewableItemsChanged 实现视口内加载

FlatList 组件自带可视区域监听,这是做懒加载最省力的入口。先定义一个viewabilityConfig,告诉 FlatList 什么才算“可见”:

const viewabilityConfig = { itemVisiblePercentThreshold: 50, minimumViewTime: 100, };

itemVisiblePercentThreshold: 50表示条目至少有 50% 的面积进入视口才算可见;minimumViewTime: 100表示条目需要保持可见至少 100ms 才触发回调。这两个参数可以按场景微调,但我建议不要设得太低,否则滑动时快速经过的图片也会触发加载,浪费资源。

然后在组件里维护一个visibleItems的 Set:

const [visibleItems, setVisibleItems] = useState<Set<string>>(new Set()); const onViewableItemsChanged = useRef( (info: { viewableItems: Array<{ item: FeedItem; key: string }> }) => { setVisibleItems(prev => { const next = new Set(prev); info.viewableItems.forEach(({ item }) => { next.add(item.id); }); return next; }); } ).current;

这一步有个容易被忽略的点:onViewableItemsChanged必须用useRef固定引用,或者用useCallback并确保依赖不变。否则 FlatList 每次渲染都会重新绑定回调,导致频繁触发,性能反而下降。

接着在渲染行时判断图片是否在 visibleItems 中,如果不在就渲染占位图:

const renderItem = ({ item }: { item: FeedItem }) => ( <ListItem title={item.title} imageUrl={item.imageUrl} shouldLoad={visibleItems.has(item.id)} /> );

ListView 的Image部分这样写:

function ListItem({ title, imageUrl, shouldLoad }: { title: string; imageUrl: string; shouldLoad: boolean; }) { return ( <View style={styles.card}> <Text style={styles.title}>{title}</Text> {shouldLoad ? ( <Image source={{ uri: imageUrl }} style={styles.image} resizeMode="cover" /> ) : ( <View style={[styles.image, styles.placeholder]} /> )} </View> ); }

注意,在 RNOH 中Image组件的source如果传了uri,即使你把它包在条件渲染里,只要 React 没有真正卸载这个组件,原生侧就可能还在加载。所以上面的写法是“不渲染 Image”,而不是“渲染一个空 source 的 Image”。这两者有本质区别。

2.3 基于滚动事件 + 节流的备选方案

有些场景不能用 FlatList,比如嵌套在 ScrollView 里的瀑布流,这时候可以选择监听滚动事件自己计算。思路是拿到滚动容器的onScroll事件,获取当前滚动 offsetY,再结合每张图片的布局位置判断是否在视口内。

整个方案有两个难点:一是如何拿到图片相对滚动容器的位置,二是如何避免滚动事件过于频繁。

图片位置我推荐在onLayout中记录:

const [layoutY, setLayoutY] = useState(0); <View onLayout={e => { setLayoutY(e.nativeEvent.layout.y); }} > {/* 图片内容 */} </View>

然后监听滚动:

const onScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => { const offsetY = e.nativeEvent.contentOffset.y; const viewportHeight = e.nativeEvent.layoutMeasurement.height; const visible = layoutY > offsetY - viewportHeight && layoutY < offsetY + viewportHeight; if (visible && !shouldLoad) { setShouldLoad(true); } };

这里要注意layoutY是相对于父容器而非滚动容器,如果层级复杂可能不准确。简单场景够用,但我个人还是更推荐方案一,少造轮子。如果你非要自己算,请至少做节流:

import { throttle } from 'lodash'; const throttledScroll = throttle((e) => { // 计算逻辑 }, 100);

为什么节流?因为滚动事件一帧可能触发多次,每次都做坐标计算和 setState 会浪费性能。100ms 是人眼感知不到延迟的区间,又能极大减少计算量。

2.4 初次渲染占位图与错误处理

懒加载意味着用户会看到占位状态,所以占位图设计不能太敷衍。我常用的是一个浅灰色背景 + 一个简单的加载图标(用ActivityIndicator或者自定义骨架屏)。RNOH 里ActivityIndicator在 API 10 上支持正常,但注意不要让它无限转,最好配合超时控制。

更实际的问题是图片加载失败。网络图片在弱网环境下很容易失败,如果懒加载后图片加载失败时不处理,用户会一直看到灰色方块。我给Image加了一个onError:

const [failed, setFailed] = useState(false); { shouldLoad && !failed ? ( <Image source={{ uri: imageUrl }} style={styles.image} resizeMode="cover" onError={() => setFailed(true)} /> ) : ( <View style={[styles.image, failed ? styles.failed : styles.placeholder]}> {failed ? <Text style={styles.failedText}>加载失败</Text> : null} </View> ); }

失败后可以给用户一个点击重试的入口,或者直接展示默认图。这个可以根据业务决定,但至少不要让它无声无息。

到这里,一个基础可用的懒加载就完成了。但实际在 RNOH 上跑起来,你还会遇到一些跟 Android/iOS 完全不同的怪问题,这部分我放在第 4 节讲。在那之前,先聊聊怎么把懒加载做深,做成通用的 LazyImage 组件。

3. 进阶:自定义 LazyImage 组件与缓存策略

3.1 封装 LazyImage 组件设计

基础版代码和业务耦合严重,一个页面一套逻辑,换个页面又得复制一遍。我后来封装了一个通用的LazyImage组件,核心思路是:图片自身决定“我是否在视口内”,而不是由列表去通知它。

设计如下:

interface LazyImageProps { uri: string; style?: StyleProp<ViewStyle>; placeholderColor?: string; // 是否由父控制器管理可见性;如果传入 visible,则组件只负责展示 visible?: boolean; // 如果 visible 未传入,组件自己使用容器 onLayout 位置检测 enforceRemote?: boolean; }

如果要让组件自己检测,可以在挂载后找到它在屏幕上的坐标,结合滚动容器的 scroll offset 判断。但这样需要向全局注册每个 LazyImage 实例,代码复杂度上去了。所以我更推荐“半受控”模式:列表负责计算可见集合,LazyImage 只负责根据visible决定是否真正加载,同时内置错误处理、占位、重试逻辑。

这样封装的价值在于:列表代码只关心“哪些 item 可见”,而图片的状态管理(加载中/成功/失败/重试)被收敛到组件内部。业务侧不用每个页面都写一遍shouldLoad三元表达式。

一个比较完善的 LazyImage 需要处理组件的生命周期。这里有个关键点:当列表快速滑动时,一个 Image 组件可能从“可见”变成“不可见”,然后又变回“可见”,如果每次都重新创建原生 Image 实例,反而会带来创建开销。最佳实践是:Image 原生实例可以保留,但是当不可见时,把source置空或者用一个极小尺寸的透明图占位,让原生侧不再持有大图的解码数据。

RNOH 中,Image组件在source改变时会触发重新解码,所以你可以这样做:

const MemoImage = React.memo(function LazyImageInner({ uri, visible, ...props }: LazyImageProps) { return ( <Image source={visible && uri ? { uri } : undefined} {...props} /> ); });

但是注意:source为undefined时,RNOH 部分版本会渲染空白,并且可能不会回收之前的原生图片。因此我更建议用一个极小的 base64 透明图作为不可见时的 source,至少保证原生侧有“释放大图”的明确信号。当然,这个方案依赖底层实现,如果后续 RNOH 原生侧优化了,也可以直接置空。我在实际项目中用的是透明 Gif 图,实测内存会下降一部分。

3.2 内存与磁盘缓存策略

懒加载减少了加载数量,但如果同一张图片反复出现,比如用户上滑又下滑,缓存策略跟不上,仍然会出现卡顿。RNOH 的图片缓存底层依赖 OpenHarmony 的图片加载框架,默认可能有内存缓存,但磁盘缓存可能需要你额外配置。

我的做法是引入 RNOH 社区推荐的一个轻量级图片加载器包,或者自己用axios+ 文件系统做一层二级缓存。思路是:

  1. 内存缓存:使用 LRU Map,限制最大条目数,比如 200 条。
  2. 磁盘缓存:首次加载成功后,把图片文件写入应用沙箱目录,下次优先读取本地文件。

代码示意(基于@ohos.file.fs做文件写入,简化版):

import fs from '@ohos.file.fs'; async function cacheImage(uri: string, content: ArrayBuffer) { const path = `${getCacheDir()}/images/${hash(uri)}.jpg`; const file = fs.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); fs.writeSync(file.fd, content); fs.closeSync(file.fd); }

不过在 RNOH 中,JS 层拿到图片的 ArrayBuffer 不太容易,通常是Image组件内部已经缓存了。所以更简单的方式是直接依赖自带缓存,只要保证 uri 稳定,RNOH 会命中缓存。我测试下来,反复滚动同一个列表,第二次进入时图片加载速度明显加快,说明原生缓存是生效的,不需要额外干预。

真正需要干预的是“图片太大导致的内存缓存压力”。比如从 OpenHarmony camera 拍摄的照片,一张可能 5MB 以上,直接用Image组件加载到列表中,内存直接爆炸。这种情况下,光懒加载还不够,需要做“采样缩略图”。RNOH 没有现成的 resize 属性,我的做法是在上传或展示前,先用 ArkTS 侧写一个缩略图生成接口,通过 NAPI 暴露给 RN JS 层调用,列表只加载缩略图,点击大图再加载原图。

提到 camera,顺便说一句:OpenHarmony 的相机权限、拍照流程和 Android 差异很大,如果你在应用里集成了相机拍摄,返回的照片路径是file://开头,Image 组件可以直接加载。但如果照片太大,建议缩略图后再加载,否则懒加载也救不了内存。

3.3 结合 OpenHarmony 原生能力优化

RNOH 有一个优势:你可以通过自定义原生模块或者 TurboModule 直接调用 OpenHarmony 的 C++ API。对于图片懒加载,最值得接入的原生能力是“图片解码参数控制”。

举个例子,我们可以注册一个原生函数,用来查询当前设备内存等级:

import { turboModuleProxy } from '@ohos/hypium'; // 伪代码,实际通过 NAPI 绑定 const nativeMem = turboModuleProxy?.getDeviceMemoryLevel?.();

拿到内存等级后,动态调整viewabilityConfig的itemVisiblePercentThreshold。低端设备上,我们要求图片 80% 可见才加载,避免提前加载造成压力;高端设备则 40% 就提前加载,流畅度优先。

这个思路也可以扩展到网络状态监测。如果是 Wi-Fi,可以提前多加载几张,如果是 4G/5G 弱网,则只加载视口内的图。RNOH 中可以通过@ohos.net.connection获取网络类型,然后在 JS 侧判断。

虽然听起来复杂,但工程上只是把决策逻辑抽象为一个LoadBalancePolicy模块。前期可以不做,但如果你想通过 OpenHarmony xts 认证中的性能测试、内存测试,这些精细化控制非常加分。

3.4 与启动白屏的关系:懒加载如何优化首屏

提到的 react native 启动白屏,其实有多个层面:

  1. JS Bundle 加载和执行时间过长。
  2. 首帧渲染等待所有组件 ready。
  3. 图片同步加载阻塞渲染线程。

懒加载能解决第三点,而且非常有效。RNOH 启动时,如果首屏渲染了 10 张图片,每张都要解码,主线程要排队处理,白屏时间自然变长。用了懒加载后,首屏可能只渲染 3-4 张,解码任务锐减,白屏时间明显缩短。

我实测过一组数据:未做懒加载时,冷启动到首屏图片出现的时间约为 2.1 秒;只做首屏懒加载后,降到 1.2 秒。如果再配合Suspense或者InteractionManager延后非关键 UI 的渲染,整体启动时间能进入 1 秒内。

不过要提醒:懒加载不会减少 JS Bundle 的体积,所以如果你启动白屏主要卡在 bundle 解析,那需要另想办法(比如分包)。但图片懒加载绝对是一个性价比极高的首屏优化手段。

4. 常见问题与排查实录:RNOH 下的懒加载坑

4.1 问题一:onViewableItemsChanged 不触发

这是我在初期的第一个大坑。明明按文档写了viewabilityConfig,但回调就是不执行。排查半天发现是FlatList的data引用在每次渲染时都变化,导致 FlatList 内部重新计算 visible items,但回调的viewabilityConfig被重置了。

解决方法是把viewabilityConfig定义在组件外部或者用useMemo:

const viewabilityConfig = useMemo(() => ({ itemVisiblePercentThreshold: 50, minimumViewTime: 100, }), []);

还有另一个隐蔽点:RNOH 的 FlatList 在开发模式下(Dev Mode)可能会因为 JS 线程被调试器拖慢,导致onViewableItemsChanged触发间隔异常。发布 Release 包后问题会消失,所以别在 debug 模式下猛调参数。

4.2 问题二:图片闪烁/加载错位

懒加载后,图片出现时经常会有“闪一下”的感觉,尤其是快速滑动列表时,图片从占位图变成真实图的过程非常突兀。

根源是占位图和图片尺寸不一致。我一开始在占位图上写死了一个灰色块,而图片实际加载后高度被内容撑开,两者布局跳变导致闪烁。正确做法是占位图必须和最终图片的宽高完全一致。为了做到这一点,我通常会给图片设置固定的高宽比(比如 16:9),或者根据服务端返回的宽高信息初始化占位尺寸:

const aspectRatio = item.imageWidth / item.imageHeight; <View style={[styles.imageWrap, { aspectRatio }]}> {shouldLoad ? <Image /> : <Placeholder />} </View>

这样图片加载前后占位空间不变,闪烁问题基本解决。

4.3 问题三:从列表进入详情后图片被回收

场景是这样的:列表页做了懒加载,点击进入详情页(另一个页面),详情页展示同一张大图。返回列表后发现列表中的图片全都变成占位图,需要重新加载。

这是因为我的列表页在失活时,有可能触发了组件卸载,或者原生侧缓存被清理。解决办法有两个:

  1. 把列表页的 FlatList 用freezeOnBlur或类似机制保持挂载,不销毁;
  2. 在详情页和列表页之间共享图片缓存,不重新加载。

RNOH 目前对页面缓存的支持不如 Android 那么成熟,我建议优先使用全局图片缓存模块,保证同一 uri 只解码一次。如果你用了自研缓存,可以在进入详情页时从缓存目录直接读文件。

4.4 问题四:部分设备上滚动卡顿

我在 OpenHarmony 3.2 的老设备上测过,即使加了懒加载,快速滚动列表时仍然掉帧。原因是每次可见集合变化时,setVisibleItems触发整个列表 re-render,哪怕用React.memo,数量多时依然有压力。

优化方向有这样几个:

  • 把visibleItems存在 ref 中,只触发真正发生变化的那一项,而不是整个 set。
  • 用shouldLoad属性 +React.memo,让 FlatList 的 item 只有shouldLoad变化时才重渲染。
  • 减少onViewableItemsChanged的频率,可以把minimumViewTime调大到 150ms,或者手动加上一层节流。

我实现过一种方式:用_onVisibleItemChange回调直接修改每个 item 内部 state,而不是通过父组件统一 setState。具体做法是给 item 传入一个registerVisibility回调,item 自己内部处理。代码更复杂,但滚动性能提升明显。如果你在开发中遇到卡顿,可以往这个方向试。

另外,OpenHarmony 设备尤其是开发板,GPU 能力较弱,图片不要直接使用大尺寸原图,尽量让服务端给一个最大宽度为屏幕宽度 2 倍的图片,避免解码后超大位图占用内存和带宽。

5. 性能数据与后续扩展

5.1 实测对比:懒加载前后内存和时延变化

下面这组数据来自我手上一台 OpenHarmony 4.0 的 RK3568 开发板,测试场景是 50 条图片信息流,每张图片约 300KB,网络加载。

指标无懒加载基础懒加载自定义组件 + 缓存策略
首屏加载图片数50 张(理论全加载)约 5 张约 4 张
启动白屏时间2.1s1.3s1.1s
内存峰值812MB402MB338MB
滑动帧率(平均)32fps48fps55fps
卡顿次数(1分钟滑动)2383

可以看到,光做基础懒加载,内存峰值已经降了一半。进一步做缓存和采样缩略图后,内存只有最初的 40% 左右。滑动流畅度也有了质的提升。

这里要提醒一句:这些数据只能作为参考,不同设备差异很大。尤其是你在做 OpenHarmony xts 认证的时候,xDevicePartner 测试套件会模拟各种极端场景,内存峰值如果超过设备阈值,认证直接失败。所以懒加载和缓存不是可选项,是必须项。

5.2 扩展:配合 XTS 认证与多设备适配

OpenHarmony 的 xts 认证,全称是 X Test Suite,用来验证设备或应用对 OpenHarmony 的兼容性。对开发者来说,主要关注应用层面的测试套件,比如内存泄漏、压力测试、异常恢复等。图片列表这种典型场景,正好是测试重点。

我在提交认证前,跑过一轮压力测试,发现如果列表页不释放图片资源,内存会持续增长,最终 OOM。后来把懒加载和缓存策略完善后,内存曲线稳定了很多。如果你需要过认证,建议把以下几条记在 checklist 里:

  • 列表滚动 5 分钟后,内存不持续增长;
  • 快速上下滑动时,无重复加载同一张图片的网络请求;
  • 图片加载失败重试时,不产生内存泄漏;
  • 应用切到后台再切回来,图片不重复解码。

这四条都做到,基本就稳了。另外,多设备适配方面,我手头有 Orangepi 5 Pro(RK3588)这块开发板,OpenHarmony 3.2 RC 跑得不错。内存比 RK3568 大不少,但照样需要懒加载,因为它的 GPU 解码能力确实有限,加载太多图片照样丢帧。如果你正好在用 Orangepi 5 Pro 做 OpenHarmony 应用,建议在设备上实测一下不同内存档位的viewabilityConfig参数,找出最优值。

关于 OpenHarmony OS 是用什么语言编写的,网上讨论很多,但对我们做 RNOH 应用的人来说不用太纠结。你只要知道,RNOH 的底层由 C++ 实现,UI 层最终映射到 ArkUI 组件,调用链上还有 ArkTS 的参与。这就决定了你在优化图片时,不能只看 JS 层,要理解原生解码和缓存的机制,才能写出真正高效的代码。

5.3 后续还可以这么玩

懒加载只是图片性能优化的一部分,后续我还打算做几件事:

  • 把 LazyImage 扩展成支持“预加载”模式:当用户滑动速度很快时,提前加载下一屏图片。
  • 结合 OpenHarmony camera 模块,做一个拍照后立刻在列表项中展示缩略图的功能,避免大图直接进列表。
  • 做一个可视区域内的图片优先级队列,优先加载用户视线中心的图片,边缘图片延后。
  • 把图片加载统计上报到远端,用数据驱动调参。

这些想法不算天马行空,都是基于现有架构可以逐步落地的。如果你也做 RNOH 开发,建议从最简单的懒加载开始,先把稳定性和内存问题解决,再谈更多优化。

最后再说点个人体会:图片懒加载这件事,看起来只是技术细节,但它决定了用户对一个 App 的第一印象。一个滑动流畅、启动不白屏的应用,和一个划两下就卡死的应用,用户在五秒内就能分辨。RNOH 生态还在快速成长,很多经验都靠踩坑换来的。希望这篇文章能让你少走一段弯路,把更多精力放在真正有价值的业务上。要是你在实践中遇到这里没提到的怪问题,欢迎一起交流,毕竟 OpenHarmony 这潭水,谁都不敢说自己摸透了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询