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

FlatList vs FlashList pe Android ieftin: Am măsurat FPS-ul real și diferența e uriașă

De Andreea Crăciun, 24 iul. 2026 · 9 vizualizări · 2 like-uri

Postat 24 iul. 2026
typescript
import React from 'react';
import { FlashList } from '@shopify/flash-list';
import { ProductCard, Product } from './ProductCard';

interface ProductListProps {
  products: Product[];
}

export const ProductList = ({ products }: ProductListProps) => {
  return (
    <FlashList
      data={products}
      renderItem={({ item }) => <ProductCard product={item} />}
      estimatedItemSize={120}
      keyExtractor={(item) => item.id}
    />
  );
};

Dacă ai dezvoltat vreodată o aplicație în React Native și ai testat-o doar pe simulator sau pe telefonul tău personal mai răsărit, probabil ai crezut că listele tale merg brici. Problema apare când deschizi app-ul pe un Android ieftin și vezi cum UI FPS-ul cade în prăpastie la un scroll mai rapid. Am trecut recent prin asta la un refactoring pentru un client din retail cu un catalog măricel și am zis să măsor exact performanța din Perf Monitor.

De ce sughite FlatList pe procesoare slabe

FlatList-ul nativ din React Native funcționează, în esență, prin unmounting și mounting agresiv de componente pe măsură ce faci scroll. Pe un procesor flagship nu simți drop-urile pentru că duce hardware-ul. Dar pe un Samsung A12 sau pe un Nokia cu 3GB RAM și procesor ieftin MediaTek, operațiunile astea continue de alloc/dealloc omoară firul principal.

Am activat Perf Monitor-ul din dev menu și am dat scroll într-o listă de test cu 8.000 de iteme (carduri de produs cu imagine, două linii de text și buton).

Rezultatele cu FlatList au fost dureroase:

  • UI FPS: a scăzut dramatic până la 12-18 FPS la scroll rapid.
  • JS FPS: spike-uri urâte între 5 și 25 FPS.
  • Symptom: ecrane albe (white flashes) la greu, pentru că JS-ul nu apuca să randeze noile elemente înainte ca ele să intre pe ecran.

Garbage collector-ul din engine-ul Hermes rula ca nebunul încercând să curățe nodurile create și distruse în secvență rapidă.

Trecerea la FlashList: Măsurători concrete

Am înlocuit FlatList cu @shopify/flash-list. FlashList folosește o strategie diferită: reciclează views-urile la fel ca RecyclerView din Android nativ. În loc să distrugă componentele care ies din ecran, le păstrează instanțele în memorie și doar le actualizează props-urile cu datele noilor elemente.

Am rulat exact același benchmark pe același telefon de teste, cu exact aceeași listă de 8.000 de produse.

Rezultate după migrare:

  • UI FPS: s-a stabilizat la 57-60 FPS (fluent, aproape imposibil de deosebit de nativ).
  • JS FPS: a rămas constant peste 50 FPS.
  • Zero white flashes, indiferent cât de repede dădeam swipe peste listă.

Consumul de memorie RAM a fost inițial cu 10-15% mai mare din cauza pool-ului de reciclare, dar a rămas complet plat pe tot parcursul sesiunii, fără spike-uri cauzate de Garbage Collection.

Trade-off-uri sincere: Unde te mușcă FlashList

Arată spectaculos în numere, dar am dat și de câteva bătăi de cap până am scos codul în producție:

  1. Prop-ul estimatedItemSize este obligatoriu. Dacă pui o valoare complet greșită, scroll-ul va avea mici jump-uri sau flash-uri de layout.
  2. State-ul local din componente. Dacă folosești useState în interiorul componentei de item renderizate, starea aia va persista când view-ul e reciclat pentru alt produs! Trebuie să gestionezi starea din exterior sau să o resetezi explicit când se schimbă id-ul produsului.
  3. Dynamic heights extreme. Dacă un card are 50px și următorul are 500px în mod imprevizibil, reciclarea își pierde din eficiență și mai apar mici agățări visuale.

Voi ce folosiți în producție? Ați rămas pe FlatList bine optimizat cu getItemLayout sau ați migrat deja totul pe FlashList?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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