Upgrade to Pro — share decks privately, control downloads, hide ads and more …

List型View(FlatList)とのパフォーマンスとの戦い

 List型View(FlatList)とのパフォーマンスとの戦い

2020/5/29 React Native Meetup #10 LT

potproject

May 29, 2020
Tweet

More Decks by potproject

Other Decks in Technology

Transcript

  1. List型View FlatList とのパフォーマンスとの戦い
    @potpro
    List型View FlatList とのパフォーマンスとの戦い 1

    View Slide

  2. ⾃⼰紹介
    @potpro ぽとぷろ
    https://blog.potproject.net/
    https://mastodon.potproject.net/
    PHP / Go / JS Vue / React
    仕事で⼤体サーバサイドエンジニア
    趣味でフロントエンド/インフラエンジニア
    List型View FlatList とのパフォーマンスとの戦い 2

    View Slide

  3. 趣味でMastodonのクライアントア
    プリを作ってます
    potproject/ikuradon
    Expo Managed Workflow Eject無
    し での開発
    今時っぽいUI
    最近React Navigation v5 + React
    Hooks にすべて書き換えている

    画⾯は開発中のものです
    List型View FlatList とのパフォーマンスとの戦い 3

    View Slide

  4. 今⽇の題材
    この部分のパフォーマンスの話
    FlatList を使⽤しています
    これの話が今回はメインです
    投稿は気にしないで下さい
    List型View FlatList とのパフォーマンスとの戦い 4

    View Slide

  5. FlatList
    React NativeにおけるList型Viewの
    標準インターフェース
    ヘッダーやフッター、リフレッシ
    ュコントロール 引っ張ったら更新
    されるアレ などが標準搭載
    ListViewというものも存在したが、
    既にDeprecatedになりこちらが現
    在は標準
    List型View FlatList とのパフォーマンスとの戦い 5

    View Slide

  6. 実装例 全く知らない⼈のために
    const DATA = [
    {
    id: '1',
    title: 'First Item',
    },
    {
    id: '2',
    title: 'Second Item',
    },
    {
    id: '3',
    title: 'Third Item',
    },
    ];
    export default function App() {
    return (

    data={DATA}
    renderItem={({ item }) => {item.title}}
    keyExtractor={item => item.id}
    />

    );
    }
    List型View FlatList とのパフォーマンスとの戦い 6

    View Slide

  7. パフォーマンス問題にぶち当たる
    List型View FlatList とのパフォーマンスとの戦い 7

    View Slide

  8. FlatListのパフォーマンス問題
    実際にアプリを開発時に浮上した問題
    リスト更新時、 リストに追加がなくても 必ず1秒以上かかってしまう
    普段使いしてるとちょっと気になるレベル
    ネットワークが遅いのかなと思ったけどレスポンスは50ms以下・・・
    更新しまくるとハイスペックなはずのiPhone11 Proの発熱がマッハ
    UIのFPSもかなり落ちてしまう
    List型View FlatList とのパフォーマンスとの戦い 8

    View Slide

  9. FlatListのパフォーマンス問題
    リストの数が増えるとパフォーマンスがかなり悪化することは、
    割と知られている
    いろんなところで話された結果、最適化の⽅法についてgithubリポジトリが存在する
    https://github.com/filipemerker/flatlist-performance-tips
    ここを参考に改善していく
    List型View FlatList とのパフォーマンスとの戦い 9

    View Slide

  10. FlatListのチューニング概要
    ⼤体⼤きく分けて2つの⽅法があります
    propsのチューニング
    FlatListに渡す値を調整することでパフォーマンス改善につながることがある
    今回のケースではメリットが薄く、デメリットが多かった うまく表⽰されない、スクロ
    ールが重くなってしまうなど
    リストの構造を変える
    リスト⾃体のコンポーネントを軽くする戦略
    デメリットもある場合もあるが、場合によってはWin-Winの物もある
    こちらを主にやっていくことで、パフォーマンスに⼤きな効果があった
    List型View FlatList とのパフォーマンスとの戦い 10

    View Slide

  11. 実際に改善したこと・⼿法
    効果が⾼かったものを紹介
    最終的に割と⼀般的なReactのパフォーマンス向上⽅法になったので、
    FlatList以外にも使える⽅法だと思います
    List型View FlatList とのパフォーマンスとの戦い 11

    View Slide

  12. 改善 1 Viewの数を減らす
    Viewの数を減らし、シンプルにする
    1つ増えるとリストの数だけ増える為、レンダリングコストが上がる
    計算量:O n になり塵も積もれば⼭となる存在に










    ↑こういった Viewの無駄遣いを辞める
    こんなことしなくてもstyleをうまく使えば⼤体やりたいことは実現できるはず
    List型View FlatList とのパフォーマンスとの戦い 12

    View Slide

  13. 改善 2 List内部でReact ReduxのStoreを使わない
    Rowの中で useSelector
    クラスなら connect
    を使わない
    コストが⾼い為、FlatListの外でuseSelectorをして、Propsで渡す
    これも計算量0 n の問題
    export default function App() {
    // Redux Store
    取得
    const data = useSelector(reducer);
    return (

    data={data}
    renderItem={({ item }) => {item.title}}
    keyExtractor={item => item.id}
    />

    );
    }
    List型View FlatList とのパフォーマンスとの戦い 13

    View Slide

  14. 改善 3 React.memo useMemo を使う
    どちらもデータを保持しておき、データを⽐較してレンダリングしないできるパフォーマンス
    改善⽤機能
    React.memo
    はコンポーネント全体、 useMemo
    は⼀部に使⽤可能
    この2つはfunctional component⽤なので、クラスは PureComponent
    を使う
    更新されない場合はレンダリングされないので、パフォーマンスが⼤幅に向上
    しかし要件にうまく合っていないと不具合となってしまうので注意
    今の時間を表⽰する、みたいなものはうまく動作しなくなる可能性あり
    List型View FlatList とのパフォーマンスとの戦い 14

    View Slide

  15. React.memo 使⽤例
    export default function App() {
    // Redux Store
    取得
    const data = useSelector(reducer);
    //Props
    で受け渡す
    return (

    data={data}
    extraData={data}
    renderItem={({ item }) => }
    keyExtractor={item => item.id}
    />

    );
    }
    function List({id, title}){
    return (

    {title}

    );
    }
    // React.memo()
    の引数にReact
    コンポーネントを渡す
    //
    旧Props
    と新Props
    を⽐較して判断します
    // ID
    とタイトルが変更された時だけレンダリング
    const Row = React.memo(List, (p, n) => p.id === n.id && p.title === n.title);
    List型View FlatList とのパフォーマンスとの戦い 15

    View Slide

  16. 改善後
    Before: リスト更新時の処理: 1200 更新0件 〜2000 更新40件 ms
    After: リスト更新時の処理: 50 更新0件 〜 1200 更新40件 ms
    チューニングと不要不急のレンダリングをやめたことで、かなり快適になった
    発熱もなくなりました
    List型View FlatList とのパフォーマンスとの戦い 16

    View Slide

  17. まとめ
    FlatListは使いやすいけど、パフォーマンス問題は結構⼤変
    100以上のリストをリッチに扱うと厳しくなる
    ⾊々やっても実は問題がまだまだある
    メモリ使⽤量はやっぱり⾼い、マシになったが爆速とは⾔えない
    更に解決するためにFlatList以外を使う⽅法もある
    ネイティブ実装で早いらしい bolan9999/react-native-largelist
    幅を計算する必要があるがパフォーマンスが⾼いらしい Flipkart/recyclerlistview
    まだ検証できていないので時間があるときに検討したい
    List型View FlatList とのパフォーマンスとの戦い 17

    View Slide

  18. ご静聴ありがとうございました
    List型View FlatList とのパフォーマンスとの戦い 18

    View Slide