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

FlatList vs FlashList pe Android ieftin: cum am trecut de la 20 la 60 FPS

De George Iliescu, 30 iul. 2026 · 10 vizualizări · 3 like-uri

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

type Product = {
  id: string;
  title: string;
  price: string;
  type: 'standard' | 'featured';
};

export const OptimizedList = ({ products }: { products: Product[] }) => {
  return (
    <FlashList
      data={products}
      renderItem={({ item }) => (
        <View style={item.type === 'featured' ? styles.featured : styles.card}>
          <Text>{item.title}</Text>
          <Text>{item.price}</Text>
        </View>
      )}
      // Esențial pentru performanță corectă pe Android slabe
      estimatedItemSize={88}
      // Necesar dacă ai layout-uri diferite în aceeași listă
      getItemType={(item) => item.type}
      keyExtractor={(item) => item.id}
    />
  );
};

const styles = StyleSheet.create({
  card: { height: 88, padding: 12 },
  featured: { height: 140, padding: 12, backgroundColor: '#ffe' },
});

Am avut recent de optimizat un feed infinit într-o aplicație de e-commerce cu vreo 12k utilizatori activi zilnic. Pe iOS și pe flagship-uri Android totul rula fluent, dar pe telefoane entry-level de 600 de lei (gen Samsung A12 sau Xiaomi Redmi 9) scroll-ul era un coșmar: cădea FPS-ul la 15-20 și apăreau ecrane albe. M-am decis să înlocuiesc clasicul FlatList cu FlashList de la Shopify și să măsor exact diferența cu Perf Monitor.

Problema cu FlatList pe Android

FlatList desființează și recreează componentele din DOM-ul virtual pe măsură ce faci scroll. Pe un CPU slab de Android, unmount-ul și mount-ul agresiv blochează JS thread-ul direct. Când dai scroll rapid, React Native nu mai apucă să randeze layout-ul în timp util, iar userul vede spații albe (blank spaces) sau scroll sacadat.

Pe Perf Monitor aveam UI FPS pe la 55, dar JS FPS-ul era prăbușit la 18-22 FPS când făceam scroll rapid într-o listă cu peste 3000 de produse.

Trecerea la FlashList și tehnica de Cell Recycling

FlashList nu distruge componentele când ies din ecran. În schimb, le reciclează stil RecyclerView din dezvoltarea nativă Android: păstrează instanța de View și doar schimbă datele (props-urile) care vin pe ea. Asta elimină overhead-ul creat de creearea de la zero a nodurilor nativ-bridge.

Implementarea e aproape un drop-in replacement, dar există o condiție critică: estimatedItemSize. Dacă pui o valoare total greșită acolo, ai jitter la scroll și calcul incorect al ScrollView-ului.

Ce au arătat cifrele pe Perf Monitor

Am făcut teste pe același Samsung A12 (Helio P35, 3GB RAM) cu o listă de 3000 de iteme compuse din imagine, titlu, preț și două badge-uri status:

  • FlatList: JS FPS mediu la scroll rapid: 22 FPS. Timp de randare inițial: ~420ms. Blank spaces masive la scroll agresiv.
  • FlashList: JS FPS mediu la scroll rapid: 57-60 FPS. Timp de randare inițial: ~180ms. Blank spaces aproape inexistente.

Am economisit peste 50% din timpul de mount inițial și am adus FPS-ul aproape de limita nativă a ecranului pe un procesor extrem de slab.

Trade-off-uri de care nu-ți spune nimeni

Toată lumea laudă FlashList ca pe un glonte de argint, dar m-am lovit de câteva ziduri în producție:

  1. Elemente de înălțimi ultra-dinamice: Dacă ai un feed cu imagini de rapoarte variabile (1:1, 16:9, 4:5) plus text expandabil, reciclarea poate duce la un flickering scurt de layout până când FlashList își recalculează dimensiunile.
  2. Prop-ul getItemType e obligatoriu la layout-uri hibride: Dacă ai carduri de tipuri complet diferite în aceeași listă (de exemplu: un banner la fiecare 5 produse), trebuie neapărat să folosești getItemType. Altfel, FlashList încearcă să recicleze un View de tip Card în View de tip Banner și crapă sau arată oribil.
  3. Membri de memorie un pic mai mari: RAM-ul folosit crește ușor pentru că instanțele rămân stocate în memorie pentru reciclare.

Dacă ai o listă simplă sau medie, trecerea la FlashList e no-brainer. Voi ce soluții folosiți pentru dynamic height items complexe în FlashList ca să evitați jumping-ul de layout?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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