首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在FlatList中虚拟化FlatList (RN )?

如何在FlatList中虚拟化FlatList (RN )?
EN

Stack Overflow用户
提问于 2022-02-17 04:20:48
回答 1查看 558关注 0票数 0

如何说服垂直反应本地FlatList在另一个垂直(非虚拟化) FlatList中正确地虚拟化?

到目前为止,似乎默认情况下,滚动到某个点或响应性调整大小重新呈现倾向于导致虚拟化陷入混乱。这小吃演示了这个问题。确保您在"Web“选项卡上,因为设备构建似乎是正确的。这里也有一个复制贯通码箱

更新:对于每个请求,这里也是内联代码。这是一个完整的程序,可以粘贴到一个新的expo init项目(或类似的)中,以查看奇怪的行为并对其进行实验。

代码语言:javascript
复制
import React, { useCallback } from 'react';
import { FlatList, Text, useWindowDimensions, View } from 'react-native';

// Make 200 rows for the big list (which will draw green and red with some info).
const bigListData = Array(200).fill(0).map((element, index) => index);

function onViewableChange({ viewableItems }) {
  if (viewableItems.length < 2) {
    console.log(`VIEWABLE CHANGE! Only ${viewableItems.length} visible...`);
  } else {
    console.log(`VIEWABLE CHANGE! ${viewableItems[0].index} to ${viewableItems[viewableItems.length - 1].index}`);
  }
}

function BigList() {
  const { height, width } = useWindowDimensions();
  const betweenRows = 10;
  const itemHeight = height / 8;
  const totalRowHeight = itemHeight + betweenRows;

  const renderer = useCallback(({ item }) => {
    const key = `i_${item}`;
    return <View key={key} style={{
                 backgroundColor: item % 2 ? "red" : "green",
                 height: itemHeight,
                 width: '90%',
                 marginLeft: '5%',
                 marginBottom: betweenRows }}>
      <Text>{key}, rh: {totalRowHeight}, offset: {totalRowHeight * item}, i {item}</Text>
    </View>;
  }, [itemHeight, totalRowHeight]);

  const getItemLayout = useCallback((__data, index) => ({
    index,
    length: itemHeight,
    offset: index * totalRowHeight
  }), [itemHeight, totalRowHeight]);

  return <FlatList
    data={bigListData}
    getItemLayout={getItemLayout}
    key={'flatList'}
    numColumns={1}
    onViewableItemsChanged={onViewableChange}
    renderItem={renderer}
  />;
}

function NoNestedFlatLists() {
  const windowHeight = useWindowDimensions().height;
  return <View style={{ height: windowHeight, width: '80%' }}><BigList /></View>;
}

function renderComponent({ item }) {
  if (item.type === "widget") {
    // Using height 600 here, but assume we cannot easily predict this height (due to text wrappings).
    return <View key={item.type} style={{ backgroundColor: 'blue', height: 600, width: '100%', marginBottom: 15 }} />
  }
  return <BigList key={item.type} />;
}

function NestedFlatLists() {
  const windowHeight = useWindowDimensions().height;
  const components = [{ type: "widget" }, { type: "bigList" }];

  return <FlatList
    data={components}
    key={'dynamicAppFlatList'}
    numColumns={1}
    renderItem={renderComponent}
    style={{ height: windowHeight, width: '80%' }}
    />;
}

export default function App() {
  const windowHeight = useWindowDimensions().height;
  
  // Rendering just the following has no virtualization issues.
  // The viewable change events make sense, no items suddenly disappear, no complete app meltdown...
  //return <NoNestedFlatLists />;

  // However:
  // Any useful dynamic "rows of components" architecture melts down when virtualization comes into play.
  // This sample represents such an app whose feeds have asked the app to render a "widget" followed by a
  // "bigList" who could well have a few hundred items itself and thus really needs virtualization to work
  // well on low-end devices. This demo leans on console logs. In snack.expo.dev, at time of writing, these
  // feel hidden: Click the footer bar, either on the checkmark or an empty space, and then the "Logs" tab.
  // Once you scroll down about half way in the "App", even slowly, you'll get logs like the following:
  //   Chrome: VIEWABLE CHANGE! 83 to 90
  //   Chrome: VIEWABLE CHANGE! 85 to 92
  //   Chrome: VIEWABLE CHANGE! Only 0 visible...
  //   Chrome: VIEWABLE CHANGE! 176 to 183
  //   Chrome: VIEWABLE CHANGE! 177 to 184
  // At which time, all the UI disappears. What it thinks is viewable is quite wrong. Try to scroll around,
  // but none of the mid rows are drawing. There is no easy way to repair app behavior from this state. The
  // only rows which still draw correctly during the problem are the top and bottom non-virtualizing rows.
  // 
  // As an alternate repro, you can scroll to near the middle and then resize the bottom of the window, and
  // similar virtualization problems can occur. (In our real app, we can be scrolled almost anywhere out of
  // the non-virtualizing rows, and make a 1px window resize to break the app. We have a more complex app
  // structure, but I'm hoping a fix for this snack will still be applicable to our own symptoms...)
  return <NestedFlatLists />;
}

希望我错过了一些琐碎的东西,因为很明显,本机正在尝试处理相同方向的嵌套FlatLists,而且在大多数情况下都做得很好。直到您碰巧有足够的数据项来发挥虚拟化的作用,即使这样,Web也只能失败。(我们尝试过将React一路升级到0.67.2,将本地Web升级到0.17.5,这是最新的版本-没有任何一个“世博”下拉版本在链接Snack中产生正确的行为。)我可以在这两个示例中更改什么,以便在嵌套的FlatList中进行正确的虚拟化?

EN

回答 1

Stack Overflow用户

发布于 2022-04-14 00:44:07

简单的回答是:你无法说服FlatList正确地虚拟化。至少现在(0.17),它坏了。

尽管我能够对FlatList虚拟化进行一些改进,以响应Native的0.18预览,但最终的度量问题要比我花更多时间来完全修复的还要深。(如果有人想尝试从这里开始-我建议专注于协调RNW的ScrollView和RN的ScrollView,然后深入研究ScrollView的测量结果,如果复制RN的ScrollView向RNW的演变还不够的话。)

但是,从零开始构建我们自己的虚拟化列表组件的速度要快得多。我们的ATM机专门满足我们的需求,所以很可能不会成为开源的,但谁知道呢。但如果你要走这条路..。考虑一下对滚动事件的节流反应,比如".measure“容器视图定期引用,并决定您需要呈现哪些内容,而不是只为.还有其他的方法,但这似乎奏效了。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71152486

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档