我已将react-native-firebase和AdMob模块集成到我的react本机项目中,并且一切都按预期工作(测试广告和生产中的广告)。现在,我想在我的平面列表中添加横幅(每X行数渲染一个横幅)。
这是我从服务器接收的数据的示例:
[
{
...item 1 details
},{
...item 2 details
},{
...ad details
},{
...item 3 details
},{
...item 4 details
},{
...ad details
}
]
这是平面列表组件
class ItemsList extends React.Component {
_renderItem = ({item, index}) => {
if (item.isAd) {
const unitId = Platform.OS === "ios" ? item.adIdIOS : item.adIdAndroid;
const Banner = firebase.admob.Banner;
const AdRequest = firebase.admob.AdRequest;
const request = new AdRequest();
const keyWords = item.admobKeywords || [];
keyWords.forEach(keyword => {
request.addKeyword(keyword);
});
return (
<View style={{ width:"100%", height: item.adHeight || "auto", marginTop: 5, marginBottom: 15, alignItems: 'center', justifyContent: 'center' }}>
<Banner
size={item.adSize}
request={request.build()}
unitId={unitId}
onAdLoaded={() => {}}
/>
</View>
)
} else {
renderItem()
}
}
render() {
return(
<View>
<FlatList
data={this.state.data}
renderItem={this._renderItem}
...
/>
</View>
)
};
};
问题在于,每当发生滚动事件(用户向下滚动)时,Flatlist都会重新渲染横幅(触发新请求),并且横幅会不断刷新。一段时间后,许多请求被触发,应用程序崩溃!
我知道在renderItem方法内调用网络请求不是一个好习惯,因此我也尝试了以下方法,但问题仍然相同:
const Banner = firebase.admob.Banner;
const AdRequest = firebase.admob.AdRequest;
const request = new AdRequest();
class CatalogueSalesList extends React.Component {
_renderItem = ({item, index}) => {
if (item.isAd) {
const unitId = Platform.OS === "ios" ? item.adIdIOS : item.adIdAndroid;
const keyWords = item.admobKeywords || [];
keyWords.forEach(keyword => {
request.addKeyword(keyword);
});
return (
<View style={{ width:"100%", height: item.adHeight || "auto", marginTop: 5, marginBottom: 15, alignItems: 'center', justifyContent: 'center' }}>
<Banner
size={item.adSize}
request={request.build()}
unitId={unitId}
onAdLoaded={() => {}}
/>
</View>
)
} else {
renderItem()
}
}
render() {
return(
<View>
<FlatList
data={this.state.data}
renderItem={this._renderItem}
...
/>
</View>
)
};
};
有人可以为我提供一个解决方案,说明如何在Flatlist内实施横幅广告,而无需在用户每次滚动列表时重新呈现横幅?
我使用的版本:
"react-native": "0.59.9",
"react-native-firebase": "~5.5.3"
答案 0 :(得分:0)
Flatlist组件包含onScroll事件挂钩,可用于确定何时以及什么类型的滚动发生:
onScrollBeginDrag
,onScrollEndDrag
,onMomentumScrollBegin
,onMomentumScrollEnd
使用这些内容,并使横幅组件/列表项成为有状态组件。 以下代码仅在用户不滚动且只有一次时才会呈现admob内容(及其相关的网络请求)。
如果标语组件直接来自admob,则将其包装在有状态的组件中,并执行以下操作。
List Parent Component
class CatalogueSalesList extends React.Component {
constructor() {
this.state = {
isDragging: false,
isGliding: false,
}
_renderItem = ({item, index}) => {
return (
<View>
<Banner
isDragging={this.state.isDragging}
isGliding={this.state.isGliding}
size={item.adSize}
request={request.build()}
unitId={unitId}
onAdLoaded={() => {}}
/>
</View>
)
} else {
renderItem()
}
}
render() {
return(
<View>
<FlatList
onScrollBeginDrag={
() => {this.setState({isDragging: true});}
}
onScrollEndDrag={
() => {this.setState({isDragging: false});}
}
onMomentumScrollBegin={
() => {this.setState({isGliding: true});}
}
onMomentumScrollEnd={
() => {this.setState({isGliding: false});}
}
data={this.state.data}
renderItem={this._renderItem}
...
/>
</View>
)
};
};
Banner.tsx
class Banner extends React.Component {
constructor(props) {
super(props)
this.state = {
shouldRenderAd: false,
}
}
componentDidMount() {
if (!this.props.isGliding && !this.props.isDragging) {
this.setState({
shouldRenderAd: true,
});
}
}
shouldComponentUpdate(nextProps: Props): boolean {
if (this.state.shouldRenderAd) {
// if it has already rendered the ad, don't re-render
return false;
} else if (!nextProps.isDragging && !nextProps.isGliding) {
// if stationary, ok to re-render
return true;
} else if (nextProps.isDragging && !nextProps.isGliding) {
// if dragging, but not gliding, ok to re-render
return true;
} else {
// otherwise (it is gliding) don't re-render
return false;
}
}
componentDidUpdate() {
if (!this.props.isGliding && !this.props.isDragging) {
// if no scrolling is happening
this.setState({
shouldRenderAd: true,
});
}
}
render() {
if (this.state.shouldRenderAd) {
return (
// render your admob (network requests) stuff here
);
} else {
return (
// Placeholder component for your ad
// probably an empty view the same dimensions as the ad banner
);
}
}
}