eduardweb.
React Native & ExpoIntermediar#performance#react-native#android#flashlist

FlatList vs FlashList pe Android ieftin: cum am trecut de la 22 la 58 FPS

De Maria Vasilescu, 23 iul. 2026 · 7 vizualizări · 3 like-uri

Postat 23 iul. 2026
typescript
import React, { useCallback } from 'react';
import { Text, View, StyleSheet } from 'react-native';
import { FlashList } from '@shopify/flash-list';

type Item = { id: string; title: string; type: 'HEADER' | 'CARD' };

export const ProductList = ({ data }: { data: Item[] }) => {
  const renderItem = useCallback(({ item }: { item: Item }) => (
    <View style={styles.card}>
      <Text>{item.title}</Text>
    </View>
  ), []);

  const getItemType = useCallback((item: Item) => item.type, []);

  return (
    <FlashList
      data={data}
      renderItem={renderItem}
      estimatedItemSize={120}
      getItemType={getItemType}
      keyExtractor={(item) => item.id}
    />
  );
};

const styles = StyleSheet.create({
  card: { height: 120, padding: 16, backgroundColor: '#fff' },
});

Anul trecut am lucrat la o aplicație de e-commerce unde trebuia să randăm un feed cu peste 8.000 de produse pe un Samsung A12 obosit. Când dădeai scroll mai repede în FlatList, ecranul îngheța, JS thread-ul pica în 15-20 FPS și apăreau spațiile alea albe insuportabile. Am făcut refactoring la @shopify/flash-list și am măsurat totul cu Perf Monitor și Flipper.

De ce crapă FlatList pe un Android entry-level

FlatList e practic un VirtualizedList sub capotă. Problema e că unmount-ează componentele când ies din viewport și creează altele noi când faci scroll. Pe un flagship nu simți asta pentru că procesorul duce. Dar pe un procesor ieftin MediaTek de pe telefoane de 600 de lei, Garbage Collector-ul intră în panică din cauza alocărilor continue de memorie.

În Perf Monitor, vedeam cum UI thread-ul stătea la 60 FPS, dar JS thread-ul murea la 22 FPS. Rezultatul? Blank spaces la scroll rapid și un delay imens când utilizatorul încerca să apese pe un card în timp ce derula.

Ce face FlashList diferit (Cell Recycling)

FlashList folosește conceptul de recycling similar cu RecyclerView din Android native. În loc să distrugă componenta de React când iese din ecran, o păstrează în memorie și doar îi schimbă prop-urile pentru noul item ce intră în viewport.

Nu mai ai re-creare de views la nivel nativ, nu mai ai spam în Garbage Collector. Pe același Samsung A12, după migrare, am obținut numere mult mai bune:

  • JS FPS a urcat de la 22 la 58-60 FPS constant la scroll rapid.
  • Consumul de memorie RAM a scăzut cu aproape 35MB pentru că nu am mai avut vânturat de obiecte în heap.
  • Timpul de randare inițială s-a redus la jumătate.

Trade-off-ul despre care nu vorbește nimeni

Sună ca un glonț de argint, dar nu e. FlashList are o cerință critică: estimatedItemSize. Dacă îi dai o valoare aiurea sau dacă elementele tale variază masiv în înălțime (de la 50px la 600px în același feed), o să ai jank sever și layout jumps.

Dacă ai un feed complex cu mai multe tipuri de carduri, trebuie neapărat să folosești prop-ul getItemType. Altfel, FlashList încearcă să recicleze un layout de imagine mare într-un layout de text scurt și o să vezi glitch-uri vizuale urâte pe Android.

Setup-ul minim care funcționează brici

Mai jos e un exemplu rapid cu tipizarea corectă și folosirea getItemType pentru a evita problemele de reciclare când ai carduri diferite în listă.

Dacă aveți liste simple sau medii, FlashList e no-brainer în 2024. Voi mai folosiți FlatList la proiecte noi sau ați trecut direct pe FlashList?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.