【问题标题】:react native flatlist is slow with dynamic items and a big datareact native flatlist 对于动态项目和大数据来说很慢
【发布时间】:2021-08-02 13:32:13
【问题描述】:

我已经使用这个问题React native grid like instagram 实现了一个类似 Instagram 探索页面的列表 但是对于我的 布局,它根本没有性能。还有其他方法可以实现吗?

另一个问题是在滚动时为某些行重新渲染不同的项目,我设法通过更改应该渲染项目的条件来减少它,但仍然存在问题。

我在这里上传了我的应用的视频:https://youtu.be/gP7kbwKDeNA

我将我的内容 chunck 转换为 3 个项目数组,然后将其传递给这个组件这是我的代码:

const albumIcon = require("../../assets/icons/stream.png");
const videoIcon = require("../../assets/icons/play.png");

const { width } = Dimensions.get("window");

let isLeft = false;
let url = null;
let icon = null;

function CustomGridList(props){
    const onRefresh = (loadMore = false) => {
        if (loadMore === true) {
            loadMore();
        } else {
            props.refresh(props.query);
        }
    };

    const loadMore = () => {
        props.refresh(props.query, true);
    };

    const getItemKey = (index,item) => {
        return "item".concat(index);
    };

    const _renderPhoto = (item, isLarge) => {
        url = null;
        icon = null;
        if (item && item.videos.length > 0) {
            url = item.videos[0].thumbnail;
            icon = videoIcon;
        } else if (item && item.images.length > 1) {
            url = item.images[0].url;
            icon = albumIcon;
        } else if(item && item.images.length > 0){
            url = item.images[0].url;
        }else{
            url = 'https://castlebba.co.uk/wp-content/uploads/2017/04/default-image-620x600.jpg'
        }
        return (
            <TouchableOpacity style={{marginRight: 1}}>
                <CachedImage
                    source={{uri: url}}
                    style={{ flex: 1}}
                    afterClickFunc={() => console.log('clicked')}
                    useTouchableOpacity
                    width={isLarge ? (width*(2/3)+4) : width/3}
                    height={isLarge ? 200: 100}
                />
                <View
                    style={{
                        position: 'absolute',
                        top: 4,
                        right: 4,
                    }}
                >
                    <CustomIcon boldColor={'#fff'} icon={icon} />
                </View>
            </TouchableOpacity>
        );
    };

    const _renderRow = (index, item) => {
        console.log(index, item );
        console.log('indexable -> ', ++index%3 );
        let item1 = item[0] !== null? item[0]: null;
        let item2 = item[1] !== null? item[1]: null;
        let item3 = item[2] !== null? item[2]: null;
        if((index+1) % 3 === 0){
            if (isLeft){
                isLeft = false;
            }else{
                isLeft = true;
            }
            return (
                <View style={{flexDirection: isLeft? 'row' : 'row-reverse', height: 200}}>
                    {_renderPhoto(item1, true)}
                    <View style={{flexDirection: 'column'}}>
                        <View style={{flex:1, height: 100}}>
                            {_renderPhoto(item2,false)}
                        </View>
                        <View style={{ flex:1, height: 100}}>
                            {_renderPhoto(item3,false)}
                        </View>
                    </View>
                </View>
            );
        }else{
            return (
                <View style={{flexDirection: 'row', height: 100}}>
                    {_renderPhoto(item1, false)}
                    {_renderPhoto(item2, false)}
                    {_renderPhoto(item3, false)}
                </View>
            );
        }
    }

    const { loading, content } = props;

    if(loading && !content) {
        return (
            <View style={{ marginTop: 30, height: 100, alignItems: 'center' }}>
                <ActivityIndicator
                    color={getThemeStyle().color_main}
                    size={'large'}
                />
            </View>
        );
    }
    if (content === null) {
        return <View />;
    }
    return (
        <View style={styles.flatListUserListWrapper}>
            <View style={styles.albumContainer}>
                <CustomFlatList
                    {...props}
                    showsVerticalScrollIndicator={false}
                    style={[
                        styles.albumContainer,
                        content.length > 0 ? { margin: 1 } : {},
                    ]}
                    content={content}
                    renderItem={({ index,item }) => _renderRow(index,item)}
                    itemSeparator={() => <View style={{ width: '100%', height: 1 }} />}
                    keyExtractor={(index,item) => getItemKey(item)}
                    enableLoadMore={true}
                    loading={loading}
                    onRefresh={() => onRefresh()}
                    loadMore={()=>loadMore()}
                    pagePostType={"search"}
                    canSendPost={false}
                />
            </View>
        </View>
    );
}

CustomGridList.propTypes = {
    error: PropTypes.string,
    loading: PropTypes.bool,
    refresh: PropTypes.func,
    navigation: PropTypes.object,
    content: PropTypes.array,
    query: PropTypes.string,
    navigateTo: PropTypes.func, //TODO implement this one on click
};
export default CustomGridList = React.memo(CustomGridList);

【问题讨论】:

    标签: react-native react-native-android react-native-ios react-native-flatlist


    【解决方案1】:

    分隔不同的行并将它们放在不同的文件中,然后改变了我选择带有大图块的行的方式,它变得更好了一点,但仍然比预期的要重新渲染更多。我没有动态地做任何事情。

    const albumIcon = require("../../../assets/icons/stream.png");
    const videoIcon = require("../../../assets/icons/play.png");
    
    const { width } = Dimensions.get("window");
    
    let isLeft = false;
    let url = null;
    let icon = null;
    function CustomGridList(props){
        const onRefresh = (loadMore = false) => {
            if (loadMore === true) {
                loadMore();
            } else {
                props.refresh(props.query);
            }
        };
    
        const loadMore = () => {
            props.refresh(props.query, true);
        };
    
        const getItemKey = (index,item) => {
            return "item".concat(index);
        };
    
        const _renderRow = (index, item) => {
            if((index+1)%6 === 0){
                return(<LargeTiledRow item={item} width={width} reverse={false} navigateTo={props.navigateTo}/>)
            }else if((index+4)%6 === 0){
                return(<LargeTiledRow item={item} width={width} reverse={true} navigateTo={props.navigateTo}/>)
            }else{
                return (<GridSimpleRow item={item} width={width} navigateTo={props.navigateTo}/>);
            }
        }
    
        const { loading, content } = props;
    
        if(loading && !content) {
            return (
                <View style={{ marginTop: 30, height: 100, alignItems: 'center' }}>
                    <ActivityIndicator
                        color={getThemeStyle().color_main}
                        size={'large'}
                    />
                </View>
            );
        }
        if (content === null) {
            return <View />;
        }
        return (
            <View style={styles.flatListUserListWrapper}>
                <View style={styles.albumContainer}>
                    <CustomFlatList
                        {...props}
                        showsVerticalScrollIndicator={false}
                        style={[
                            styles.albumContainer,
                            content.length > 0 ? { margin: 1 } : {},
                        ]}
                        content={content}
                        renderItem={({ index,item }) => _renderRow(index,item)}
                        itemSeparator={() => <View style={{ width: '100%', height: 1 }} />}
                        keyExtractor={(index,item) => getItemKey(item)}
                        enableLoadMore={true}
                        loading={loading}
                        onRefresh={() => onRefresh()}
                        loadMore={()=>loadMore()}
                        pagePostType={"search"}
                        canSendPost={false}
                    />
                </View>
            </View>
        );
    }
    
    function areEqual(prevProps, nextProps) {
        prevProps.content === nextProps.content
    }
    
    export default CustomGridList = React.memo(CustomGridList,areEqual);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-18
      • 2022-12-24
      • 1970-01-01
      • 2018-04-01
      • 2021-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多