Comment améliorer les performances de rendu FlatList pour large list avec la réactionnelle 0.43?

j'essaie d'afficher une liste de ~250 images en 3 colonnes à l'aide de FlatList dans RN0.43, et j'ai modifier la largeur de l'image dans les onLayout fonction de la FlatList pour s'adapter à la largeur de l'écran.

la performance initiale est ok, mais après un certain scrolling haut/bas, il faut parfois une seconde ou deux jusqu'à ce que les images soient affichées.

c'est encore pire si je passe à l'orientation de l'écran, il faut 2~3 secondes pour mettre l'écran à jour.

quelques résultats:

  1. après la rotation de l'écran, il faut une seconde ou deux jusqu'à FlatList.onLayout s'appelle

  2. après FlatList.onLayout et mise à jour de la largeur de l'image, chaque image (environ la moitié de la liste, ~150 images; alors que seulement ~15 sont affichées) est rendue 2~4 fois, tandis que render() n'est appelée qu'une fois.

question:

  1. comment puis-je modifier le code pour améliorer les performances?
  2. dans le getItemLayout () d'une liste multicolumn, le décalage doit-il ressembler à (itemHeight + separatorHeight) * (index%numColumns)?

Merci.

testé sur: GalaxySII (4.1.2) et Android SDK emulator (7.1.1)

var data = [
    require('./res/img/Search.png'),
    require('./res/img/test - Copy.png'),
    // ~250 items
    ...];

class app extends React.Component {
    renderItem (info, width) {
        console.log('renderItem', info.index);
        if(width !== this.width) {
            this.imageStyle = {width: width-MarginHorizontal , height: width-MarginHorizontal, resizeMode: 'contain'};
        }
        return (
            <Image
                source = {info.item}
                key = {info.index}
                style={this.imageStyle}/>
            );
    }

    render() {
        console.log('Test.render');
        return (
            <View style={{
                flex: 1,
                flexDirection: 'row',
                justifyContent: 'flex-start',
                alignItems: 'center',
                backgroundColor: '#F5FCFF'
            }}>
                <GridList
                    numColumns={3}
                    columnWrapperStyle={{ alignItems: 'center', marginVertical: 5, justifyContent: 'space-around'}}
                    data={data}
                    renderItem={this.renderItem}
                />
            </View>
        );
    }
}

class GridList extends Component {
    onLayout(event) {
        console.log('GridList.onLayout()');
        let newColumnWidth = event.nativeEvent.layout.width/ this.numColumns;
        this.layout = Object.assign({},event.nativeEvent.layout);
        if( undefined === this.columnWidth  || Math.abs(newColumnWidth - this.columnWidth) > WidthTolerance ) {
            this.columnWidth = newColumnWidth;
            if(this.isComponentMounted) {
                this.setState({renderCount: this.state.renderCount+1});
            } else {
                this.state.renderCount +=1;
            }
        }
    }
    render() {
        console.log('GridList.render()');
        return (
            <FlatList
                {...(this.modifiedProps)}
                renderItem={(info) => { return this.props.renderItem(info, this.columnWidth); }}>
                {this.props.children}
            </FlatList>
        );
    }
}
16
demandé sur John Ng 2017-04-13 06:32:04

4 réponses

Avertissement: je sais que la question est ancienne, mais voici ma réponse de toute façon.

Mon application a une main pleine de listes avec+ de 500 articles. Donc, nous sommes arrivés à un point où l'application s'écrasait sur les téléphones populaires pas mal. Puis j'ai fait cette recherche approfondie sur la performance sur les Flatlistes.

FlatList la composante a été présentée comme une alternative pour les anciens ScrollView. Le problème est que ScrollViews affiche toute votre liste à la fois afin qu'ils effectuer visuellement mieux, mais il ya un compromis dans la consommation de mémoire, qui conduit à des accidents app.

donc les listes plates sont un mal nécessaire. Ils ne rendent essentiellement que des objets qui sont visibles, ce qui est un gain énorme sur la consommation de mémoire, mais une douleur pour la performance visuelle, spécialement pour les articles lourds/complexes, qui se trouve être votre cas avec ces images sensibles.

Comment contourner?

Il ya beaucoup de stratégies que vous pouvez mettre en œuvre pour atténuer votre problème.

  • utilisez des images cachées et performatiques, comme réagissent-native-rapide-image. Chaque opération que vous pouvez supprimer ou abréger pour libérer le fil Javascript: faites - le (chaque image est un new Image(), donc, si elles sont mises en cache, vous avez votre loaded crochet appelé plus tôt)

  • votre élément de liste est un élément en lecture seule, qui est supposé être "muet". Mettre en œuvre un shouldComponentUpdate() { return false } ou une méthode plus solide de contrôle de mise à jour en tant que de besoin. C'est ÉNORME perf coup de pouce.

  • enlever la console.les journaux n'importe où près de votre liste. Ils ralentissent le fil Javascript vraiment mauvais.

  • Construisez votre application pour la production et le tester. Il devient presque toujours deux ou trois fois plus rapide. Dev env est lent à cause du débogage.

  • Donner cet article une bonne lecture pour plus d' les stratégies.

Conclusion

FlatList une composante lente. C'est un question connue, ouverte et bien documentée. Faites ce que vous pouvez pour l'améliorer, et espérons que les prochaines versions pourront corriger cela.

2
répondu Filipe Merker 2018-06-06 03:28:27

Oui j'ai eu le même problème plusieurs images et vidéos dans la liste de réagir natif j'ai Donc enlevé Flatlist au lieu de cela, j'ai préféré utiliser ListView de rendre rapidement et de corriger touchability question sur un élément de liste, mais Ne pas oublier de mettre PureComponent à l'élément de liste

0
répondu priyanka 2018-05-18 19:05:56

vous recréez beaucoup d'objets stylisés pour chaque ligne de la liste individuellement. Cela met beaucoup de trafic sur le pont js - > Native. Essayez d'utiliser la feuille de style au lieu de passer les styles en ligne.

0
répondu vonovak 2018-06-02 06:41:15

essayez de définir une clé unique pour chaque élément en utilisant keyExtractor

Par Exemple:

render() {
  return (
    <List>
      <FlatList
        ...
        keyExtractor={item => item.email}
      />
    </List>
  );
}
-1
répondu Oleksandr Cherniavenko 2017-11-10 15:57:43