You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native Video因Zustand状态更新过度刷新致安卓性能下降崩溃

解决React Native中Zustand状态更新导致react-native-video过度刷新的问题

以下是针对你遇到的性能问题和安卓崩溃问题的具体优化方案:


一、精准订阅Zustand状态,减少不必要重渲染

Zustand默认会订阅整个store,任何状态更新都会触发组件重渲染。改为只订阅需要的字段,避免获取整个socialWallContents对象:

// 原代码
const { getSocialWallContent, socialWallContents } = useSocialWallStore((state) => state)

// 修改后
const { getSocialWallContent, contents, loadingMore } = useSocialWallStore((state) => ({
  getSocialWallContent: state.getSocialWallContent,
  contents: state.socialWallContents.contents,
  loadingMore: state.socialWallContents.loadingMore,
}))

二、修复Memo组件的使用方式

你当前在组件内部创建SocialContentsMemo,每次父组件重渲染都会生成新的memo组件,完全失去缓存作用。把它移到组件外部:

// 移到import语句下方,组件定义之前
import SocialContents from '../../components/Recognition/Contents'
const SocialContentsMemo = React.memo(SocialContents)

const XXX = ({ props, route }) => {
  // ... 原有代码
}

同时用useCallback稳定onDelete函数的引用,避免触发子组件不必要重渲染:

import { useCallback } from 'react'

const XXX = ({ props, route }) => {
  const onDelete = useCallback((itemId) => {
    // 你的删除逻辑
  }, [/* 依赖项:比如store中的删除方法 */])
  
  // ... 其他代码
}

三、优化FlashList的数据处理

1. 缓存排序后的数组

sort方法会返回新数组,每次重渲染都会生成新引用,导致FlashList全量重渲染。用useMemo缓存排序结果:

const wallData = useMemo(() => {
  if (!contents) return []
  // 先复制数组再排序,避免修改原数据
  return [...contents].sort((a, b) => Date.parse(b.dateCreatedUtc) - Date.parse(a.dateCreatedUtc))
}, [contents])

2. 不要用index作为key

用item的唯一ID替代index作为keyExtractor,确保列表项顺序变化时组件能正确复用:

<FlashList
  // ... 其他属性
  keyExtractor={(item) => item.id.toString()} // 替换为你的item唯一ID字段
  renderItem={({ item }) => (
    <SocialContentsMemo data={item} onDelete={onDelete} />
    // 移除多余的包裹View,减少层级
  )}
/>

四、优化视频组件的渲染逻辑

1. 缓存媒体格式判断结果

每次重渲染都会重复判断视频格式,用useMemo缓存结果:

const SocialContents = ({ data, onDelete }) => {
  const [isBuffered, setIsBuffered] = useState(false)
  
  const isVideo = useMemo(() => {
    if (!data?.mediaUrl) return false
    const videoFormats = ['.mp4', '.webm', '.avi', '.mov', '.mkv', '.flv']
    return videoFormats.some(format => data.mediaUrl.endsWith(format))
  }, [data?.mediaUrl])

  // ... 其他代码
}

2. 给视频添加缓存策略(安卓)

通过cacheKey属性让安卓端缓存相同视频,避免重复加载:

<Video
  source={{ uri: data.mediaUrl }}
  cacheKey={data.mediaUrl} // 用视频URL作为缓存标识
  style={{ width: '100%', height: 200 }}
  resizeMode="contain"
  controls={isBuffered}
  paused={true}
  shouldPlay={false} // 明确初始不播放,减少不必要加载
  onLoad={() => setIsBuffered(true)}
/>

五、其他布局优化

去掉FlashList父容器的固定宽高,改用flex:1自适应布局,避免布局计算错误引发的重渲染:

// 原代码
<View
  style={{
    height: Dimensions.get("screen").height,
    width: Dimensions.get("screen").width,
  }}
>
  <FlashList ... />
</View>

// 修改后
<View style={{ flex: 1 }}>
  <FlashList ... />
</View>

给FlashList设置合理的固定estimatedItemSize(比如400),帮助组件更好地预估布局,减少滚动时的重渲染。


内容的提问来源于stack exchange,提问作者user20951184

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 01:36:11