HarmonyOS APP开发—"图迹"旅行相册App,需要用到这个库

做一个旅行相册 App,用户上传的几百张旅途照片要瀑布流展示,点击大图要秒开。RN 自带 Image 没缓存、每次重新下载——@react-native-ohos/react-native-fast-image 的二级缓存 + 预加载,让相册体验追平原生。

📦 仓库地址:https://gitcode.com/CPF-RN/rntpc_react-native-fast-image | 安装:npm install @react-native-ohos/react-native-fast-image


写在前面

“图迹"的核心体验是"滑到就看到”——用户打开某次旅行的相册,几十张照片瀑布流排列,滑到哪里哪里就秒出图。点开大图,几乎无延迟地全屏展示。

这对图片加载的要求极高:

  • 缓存是刚需:滑过的图再滑回来不能重新下载,否则流量爆炸 + 体验卡顿
  • 大图预加载:用户看缩略图时,大图已经在后台拉好了,点开即出
  • 优先级:当前可见区域的图优先加载,不可见区域降级

RN 自带 Image 组件在鸿蒙上没有原生磁盘缓存,每次都要重新下载。react-native-fast-image 底层适配了 HarmonyOS 原生缓存引擎——内存缓存 + 磁盘缓存 + 优先级队列 + 预加载

这篇文章聊什么

  1. 瀑布流加载——FastImage + FlatList 瀑布流
  2. 大图预加载——缩略图加载时预加载高清大图
  3. 优先级控制——可见区域优先、不可见区域降级

打开旅行相册

加载缩略图列表

缓存命中?

秒出图

网络下载

存入磁盘缓存

存入内存缓存

预加载相邻大图

用户点击

大图缓存命中?

秒开大图

快速下载


第一步:安装

npm install @react-native-ohos/react-native-fast-image

第二步:瀑布流照片列表

import FastImage from '@react-native-ohos/react-native-fast-image'
import { FlatList, View, Text, Dimensions } from 'react-native'

const { width } = Dimensions.get('window')
const COLUMN_WIDTH = (width - 24) / 2 // 两列瀑布流

interface Photo {
  id: string
  thumb: string  // 缩略图 URL
  full: string   // 高清大图 URL
  title: string
}

function PhotoCard({ photo }: { photo: Photo }) {
  return (
    <View style={{ width: COLUMN_WIDTH, marginBottom: 12 }}>
      <FastImage
        style={{ width: '100%', height: COLUMN_WIDTH * 1.3, borderRadius: 8 }}
        source={{
          uri: photo.thumb,
          priority: FastImage.priority.normal,
          cache: FastImage.cacheControl.immutable, // 永不重复下载
        }}
        resizeMode={FastImage.resizeMode.cover}
      />
      <Text style={{ fontSize: 13, color: '#666', marginTop: 4 }}>{photo.title}</Text>
    </View>
  )
}

// 瀑布流列表
<FlatList
  data={photos}
  numColumns={2}
  keyExtractor={(item) => item.id}
  renderItem={({ item }) => <PhotoCard photo={item} />}
  contentContainerStyle={{ padding: 12 }}
/>

cache: FastImage.cacheControl.immutable 是关键——图片 URL 不变就永不重新请求,旅行照片一旦上传就不会变,完美匹配这个策略。


第三步:大图预加载

用户在看缩略图列表时,提前把当前可见区域相邻的几张高清大图拉进缓存:

import { useEffect, useRef } from 'react'

function usePreloadFullImages(photos: Photo[], visibleStart: number, visibleEnd: number) {
  useEffect(() => {
    // 预加载当前可见区域 + 前后各 2 张的大图
    const toPreload: Array<{ uri: string; priority: any }> = []
    for (let i = Math.max(0, visibleStart - 2); i <= Math.min(photos.length - 1, visibleEnd + 2); i++) {
      toPreload.push({
        uri: photos[i].full,
        priority: FastImage.priority.low, // 预加载用低优先级,不抢当前图
      })
    }
    FastImage.preload(toPreload)
  }, [visibleStart, visibleEnd])
}

预加载用 priority.low——不抢当前可见缩略图的带宽,等缩略图都加载完了再拉大图。


第四步:点击查看大图(秒开)

function FullScreenViewer({ photo, onClose }: { photo: Photo; onClose: () => void }) {
  return (
    <View style={{ flex: 1, backgroundColor: '#000' }}>
      <FastImage
        style={{ flex: 1 }}
        source={{
          uri: photo.full,
          priority: FastImage.priority.high, // 大图用高优先级
          cache: FastImage.cacheControl.immutable,
        }}
        resizeMode={FastImage.resizeMode.contain}
        onLoad={(e) => {
          console.log(`大图加载完成: ${e.nativeEvent.width}x${e.nativeEvent.height}`)
        }}
      />
      <TouchableOpacity onPress={onClose} style={{ position: 'absolute', top: 40, right: 20 }}>
        <Text style={{ color: '#fff', fontSize: 18 }}>✕</Text>
      </TouchableOpacity>
    </View>
  )
}

因为第三步已经预加载了大图,用户点击时缓存已命中,几乎零延迟秒开


为什么"图迹"选了 FastImage?

需求RN Image@react-native-ohos/react-native-fast-image
磁盘缓存✅ 二级缓存
预加载preload()
优先级✅ low/normal/high
缓存策略✅ immutable/web
大图秒开❌ 重新下载✅ 预加载命中缓存
进度回调onProgress

总结

"图迹"这个场景里,@react-native-ohos/react-native-fast-image 解决了三件事:

  1. 缓存不重下——immutable 策略 + 二级缓存,滑过的图再滑回来秒出
  2. 大图秒开——缩略图加载时低优先级预加载大图,点击即出
  3. 优先级调度——可见区域 normal,预加载 low,大图查看 high,带宽合理分配

如果你也在做相册、电商、社交等大量图片的 RN 鸿蒙应用,react-native-fast-image 是性能体验的底线保障。

Logo

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

更多推荐