web-dev-qa-db-ja.com

ReactNative 0.43で大きなリストのFlatListレンダリングパフォーマンスを向上させる方法は?

RN0.43のFlatListを使用して、3列で最大250個の画像のリストをレンダリングしようとしています。FlatListのonLayout関数で画像の幅を変更して、画面の幅に合わせます。

最初のパフォーマンスは問題ありませんが、上下にスクロールした後、画像が表示されるまでに1〜2秒かかることがあります。

画面の向きを変更すると、画面が更新されるまでに2〜3秒かかります。

いくつかの発見:

  1. 画面の回転後、FlatList.onLayoutが呼び出されるまで1秒または2秒かかります

  2. flatList.onLayoutと画像の幅の更新後、各画像(リストの約半分、約150の画像、15のみが表示されます)が2〜4回レンダリングされ、render()は1回だけ呼び出されます。

質問:

  1. コードを変更してパフォーマンスを向上させるにはどうすればよいですか?
  2. 複数列リストのgetItemLayout()では、オフセットは(itemHeight + separatorHeight)*(index%numColumns)のようにする必要がありますか?

ありがとう。

テスト済み:GalaxySII(4.1.2)およびAndroid SDKエミュレーター(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>
        );
    }
}
18
John Ng

免責事項:私は質問が古いことを知っていますが、とにかく私の応答です。

私のアプリには、500以上のアイテムのリストがたくさんあります。それで、人気のある悪くない電話でアプリがクラッシュするところまで来ました。次に、私は FlatListのパフォーマンスに関するこの広範な調査を行いました。

FlatListコンポーネントは、古いScrollViewの代替として提示されました。問題は、ScrollViewがすべてのリストを一度にレンダリングして視覚的に優れたパフォーマンスを発揮することですが、メモリ消費のトレードオフがあり、それがアプリのクラッシュにつながります。

したがって、フラットリストは必要な悪です。それらは基本的に、表示されるアイテムのみをレンダリングします。これはメモリ消費量を大幅に増加させますが、視覚的パフォーマンス、特に重い/複雑なアイテムの場合は、これらのレスポンシブな画像の場合に起こります。

回避策は?

問題を軽減するために実装できる戦略はたくさんあります。

  • react-native-fast-image などのキャッシュされたパフォーマンスの高い画像を使用します。 JavaScriptスレッドを解放するために削除または省略できるすべての操作:実行してください(すべての画像がnew Image()であるため、キャッシュされている場合は、より早くloadedフックが呼び出されます)

  • リストアイテムコンポーネントは読み取り専用コンポーネントであり、「ダム」であると想定されています。必要に応じて、shouldComponentUpdate() { return false }またはより確実な更新制御メソッドを実装します。これは巨大なパフォーマンス向上です。

  • リストの近くにあるconsole.logsを削除します。彼らはJavascriptスレッドを本当に遅くします。

  • アプリを本番用にビルドしてテストします。ほとんどの場合、2倍または3倍速くなります。デバッグのため、開発環境が遅い。

  • この記事 を読んで、より多くの戦略を読んでください。

結論

FlatList[〜#〜]は[〜#〜]遅いコンポーネントです。これは 既知のオープンで十分に文書化された問題です 。それを改善するためにできることをしてください。将来のリリースでこれが修正されることを願っています。

8
Filipe Merker

フラットリストを最適化するには、以下のリンクにある記事を読むことを強くお勧めします。 https://reactnative.dev/docs/0.60/optimizing-flatlist-configuration

0
Pratik Adhikari

リストの各行に対して個別に多くのスタイリングオブジェクトを再作成しています。これにより、JS-> Nativeブリッジに大量のトラフィックが発生します。インラインでスタイルを渡す代わりに、スタイルシートを使用してみてください。

0
vonovak

はい私は同じ問題を抱えていました-反応ネイティブのリスト内の複数の画像とビデオなので、代わりにFlatlistを削除しました。ListViewを使用して高速にレンダリングし、リスト項目のタッチ性の問題を修正することを好みましたが、PureComponentをリスト項目に設定することを忘れないでください

0
priyanka