对于动态项目和大数据,Reaction原生平面列表速度很慢

人气:71 发布:2023-01-03 标签: react-native react-native-android react-native-ios react-native-flatlist

问题描述

我已经使用这个问题实现了一个类似Instagram Explore页面的列表React native grid like instagram 但它与布局完全不是很好的。有没有其他方法来实现这一点?

另一个问题是重新呈现某些行的不同项目滚动时,我通过更改应呈现项目的条件来减少该问题,但仍有问题。

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

我将我的内容分块到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);

推荐答案

我分隔了不同的行,并将它们放在不同的文件中,然后更改了我选择带有大平铺的行的方式,情况稍微好了一些,但重新呈现的程度仍然超过了预期。我没有动态地做任何事情。

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);

17