-
Notifications
You must be signed in to change notification settings - Fork 24.9k
Closed
Labels
Description
Environment
React Native Environment Info:
System:
OS: macOS 10.14
CPU: x64 Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz
Memory: 9.73 GB / 16.00 GB
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 8.12.0 - /usr/local/opt/node@8/bin/node
Yarn: 1.9.4 - /usr/local/bin/yarn
npm: 6.4.1 - /usr/local/opt/node@8/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
SDKs:
iOS SDK:
Platforms: iOS 12.0, macOS 10.14, tvOS 12.0, watchOS 5.0
IDEs:
Android Studio: 3.1 AI-173.4907809
Xcode: 10.0/10A255 - /usr/bin/xcodebuild
npmPackages:
@storybook/react-native: ^3.4.11 => 3.4.11
react: 16.5.2 => 16.5.2
react-native: 0.57.2 => 0.57.2
npmGlobalPackages:
react-native-cli: 2.0.1
Description
- Image tag takes too much memory when i change its source on some button action.
- I have to show and replace about 40 images in a single component.
- After showing about 30 images app memory goes above 1GB
- All images are just a few KBs in size
- And Also it restarts phone upon testing on real Device
- Placing images in javascript code have no issue in debug mode but crashes with excessive memory usage in production mode.
- While placing images in iOS side with manual image references also produces excessive memory usage in dev mode.
Here is the memory screen shots:
Reproducible Demo
// Colors.js
const colors = {
background: '#1F0808',
clear: 'rgba(0,0,0,0)',
facebook: '#3b5998',
themeColor: '#3b5998',
transparent: 'rgba(0,0,0,0)',
silver: '#F7F7F7',
steel: '#CCCCCC',
error: 'rgba(200, 0, 0, 0.8)',
ricePaper: 'rgba(255,255,255, 0.75)',
frost: '#D8D8D8',
cloud: 'rgba(200,200,200, 0.35)',
windowTint: 'rgba(0, 0, 0, 0.4)',
panther: '#161616',
charcoal: '#595959',
coal: '#2d2d2d',
bloodOrange: '#fb5f26',
snow: 'white',
ember: 'rgba(164, 0, 48, 0.5)',
fire: '#e73536',
drawer: 'rgba(30, 30, 29, 0.95)',
eggplant: '#251a34',
border: '#483F53',
banner: '#5F3E63',
text: '#E0D7E5'
}
export default colors
\ Metrics.js
import {Dimensions, Platform} from 'react-native'
const { width, height } = Dimensions.get('window')
// Used via Metrics.baseMargin
const metrics = {
marginHorizontal: 10,
marginVertical: 10,
section: 25,
baseMargin: 10,
doubleBaseMargin: 20,
smallMargin: 5,
doubleSection: 50,
horizontalLineHeight: 1,
screenWidth: width < height ? width : height,
screenHeight: width < height ? height : width,
navBarHeight: (Platform.OS === 'ios') ? 64 : 54,
buttonRadius: 4,
icons: {
tiny: 15,
small: 20,
medium: 30,
large: 45,
xl: 50
},
images: {
small: 20,
medium: 40,
large: 60,
logo: 200
}
}
export default metrics
\ ScreenStyles.js
import {StyleSheet} from 'react-native'
import {Metrics, Colors} from '../../Themes'
export default StyleSheet.create({
container: {
flex: 1,
marginTop: Metrics.section
},
scrollContainer: {
flex: 1,
padding: Metrics.baseMargin
},
cardViewStyle: {
flexWrap: 'wrap',
marginVertical: Metrics.section
},
headerView: {
flexWrap: 'wrap',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between'
},
headerPhone: {
flexWrap: 'nowrap',
flexDirection: 'column',
justifyContent: 'flex-start',
backgroundColor: Colors.background
},
headerNameView: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
padding: Metrics.baseMargin,
margin: Metrics.baseMargin
},
buttonsView: {
flexWrap: 'wrap',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginHorizontal: Metrics.baseMargin
},
headingText: {
flex: 1,
minHeight: 55,
color: Colors.background,
padding: Metrics.smallMargin
},
lockButton: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: Colors.themeColor,
paddingVertical: Metrics.baseMargin - 1,
paddingHorizontal: Metrics.baseMargin,
marginLeft: Metrics.baseMargin
},
lockIcon: {
color: Colors.snow
},
lockText: {
color: 'white',
paddingVertical: Metrics.smallMargin,
paddingHorizontal: Metrics.smallMargin
},
arrowText: {
color: Colors.background
},
audioIcon: {
color: Colors.black
},
imageView: {
alignItems: 'center',
justifyContent: 'center'
},
image: {
height: 150,
width: 150,
alignItems: 'center',
justifyContent: 'center'
},
roundButtonsView: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
padding: Metrics.baseMargin,
marginVertical: Metrics.doubleBaseMargin
},
circleButton: {
height: 60,
width: 60,
borderRadius: 30,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: Colors.greenButton,
marginHorizontal: Metrics.doubleBaseMargin
},
progressView: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
backgroundColor: Colors.transparent,
padding: Metrics.baseMargin
},
otherView: {
marginVertical: Metrics.doubleBaseMargin,
padding: Metrics.doubleBaseMargin
},
inputView: {
borderBottomWidth: 1,
borderBottomColor: Colors.background,
marginVertical: Metrics.doubleBaseMargin,
marginHorizontal: Metrics.baseMargin
},
otherTextInputStyle: {
flex: 1,
height: 40
},
returnText: {
flex: 1,
textAlign: 'center',
alignSelf: 'center',
color: Colors.background,
padding: Metrics.smallMargin
}
})
// SelectionScreen.js
// @flow
import React, {Component} from 'react'
import Icon from 'react-native-vector-icons/MaterialIcons'
import {ScrollView, Text, View, TouchableOpacity, Dimensions, Image, TextInput} from 'react-native'
// Styles
import styles from './Styles/ScreenStyles'
import Metrics from '../Themes/Metrics'
import Colors from '../Themes/Colors'
let SYMPTOMS_ITEMS = [
'fevers.jpg',
'rigors.jpg',
'fatigue.jpg',
'weight_loss.jpg',
'weight_gain.jpg',
'swelling.jpg',
'night_sweats.jpg',
'headache.jpg',
'dizziness.jpg',
'neck_pain.jpg',
'changes_vision.jpg',
'hearing_loss.jpg',
'ringing_ears.jpg',
'swollen_glands.jpg',
'painful_swallowing.jpg',
'chest_pain.jpg',
'cough.jpg',
'sputum_production.jpg',
'hemoptysis.jpg',
'shortness_of_breath.jpg',
'painful_breathing.jpg',
'wheezing.jpg',
'nausea.jpg',
'vomiting.jpg',
'loss_of_appetite.jpg',
'bloating.jpg',
'diarrhea.jpg',
'jaundice.jpg',
'confusion.jpg',
'anxiety.jpg',
'depression.jpg',
'psychosis.jpg',
'tingling_hands.jpg',
'difficulty_sleeping.jpg',
'muscle_aches.jpg',
'joint_pain.jpg',
'itching.jpg',
'rash.jpg',
'skin_dryness.jpg',
'skin_changes.jpg',
'hair_changes.jpg',
'weakness.jpg',
'seizure.jpg'
]
export default class SelectionScreen extends Component {
constructor (props) {
super(props)
const {width} = Dimensions.get('window')
this.state = {
index: 0
}
}
handleNextPress = () => {
const {index} = this.state
if (index < SYMPTOMS_ITEMS.length - 1) {
this.setState({index: index + 1})
}
}
handleBackPress =() => {
const {index} = this.state
this.setState({index: index - 1})
}
renderIconButton = (disable, icon, action, text) => {
const style = [styles.lockButton, {backgroundColor: Colors.transparent}]
return (
<TouchableOpacity
activeOpacity={0.8}
style={style}
disabled={disable}
onPress={() => action()} >
{text !== 'Next' && <Icon name={icon} size={20} color={Colors.blackText} />}
<Text style={styles.arrowText}> {text.toUpperCase()}</Text>
{text === 'Next' && <Icon name={icon} size={20} color={Colors.blackText} />}
</TouchableOpacity>
)
}
render () {
const {index} = this.state
return (
<View style={styles.container}>
<ScrollView style={styles.scrollContainer}>
<View style={[styles.cardViewStyle]}>
<View>
<View style={styles.imageView}>
<Image
source={{uri: SYMPTOMS_ITEMS[index]}}
style={styles.image} />
</View>
</View>
<View style={styles.progressView}>
{this.renderIconButton((index === 0), 'keyboard-arrow-left', this.handleBackPress, 'Back')}
{this.renderIconButton(false, 'keyboard-arrow-right', this.handleNextPress, 'Next')}
</View>
</View>
</ScrollView>
</View>
)
}
}
Here above is the image tag used.