React Native移动应用程序在每次点击时工作都很慢。
我正在使用react native v0.40.0
,以下是我项目的依赖项。
{
"analytics-react-native": "^1.1.0",
"apisauce": "^0.7.0",
"babel-preset-es2015": "^6.18.0",
"es6-promise": "^4.0.5",
"flow-bin": "^0.36.0",
"geolib": "^2.0.22",
"immutable": "^3.8.1",
"intl": "^1.2.5",
"isomorphic-fetch": "^2.2.1",
"lodash": "^4.17.4",
"lodash.range": "^3.2.0",
"prop-types": "^15.5.10",
"raven-js": "^3.13.1",
"react": "^15.4.2",
"react-native": "^0.40.0",
"react-native-apple-healthkit-rn0.40": "^0.3.2",
"react-native-blur": "^2.0.0",
"react-native-button": "^1.7.1",
"react-native-checkbox": "^2.0.0",
"react-native-code-push": "^1.17.3-beta",
"react-native-datepicker": "^1.4.4",
"react-native-device-info": "^0.10.1",
"react-native-easy-toast": "^1.0.6",
"react-native-fbsdk": "^0.5.0",
"react-native-geocoder": "^0.4.5",
"react-native-gifted-chat": "^0.1.3",
"react-native-global-props": "^1.1.1",
"react-native-image-crop-picker": "^0.15.1",
"react-native-image-picker": "^0.25.1",
"react-native-image-slider": "^1.1.5",
"react-native-keyboard-aware-scroll-view": "^0.2.7",
"react-native-maps": "0.15.2",
"react-native-modal-dropdown": "^0.4.4",
"react-native-popup-menu": "^0.7.2",
"react-native-push-notification": "^2.2.1",
"react-native-radio-buttons": "^0.14.0",
"react-native-router-flux": "3.38.0",
"react-native-segmented-android": "^1.0.4",
"react-native-snap-carousel": "2.1.4",
"react-native-stars": "^1.1.0",
"react-native-swipeout": "^2.2.2",
"react-native-swiper": "^1.5.4",
"react-native-tableview-simple": "0.16.5",
"react-native-vector-icons": "^4.0.0",
"react-native-video": "^1.0.0",
"react-native-zendesk-chat": "^0.2.1",
"react-redux": "^4.4.6",
"recompose": "^0.20.2",
"redux": "^3.5.2",
"redux-thunk": "^2.0.1"
}
我在android工作室中使用stacktrace进行了分析,发现mqt_js是每次UI点击需要更多时间的原因之一。您可以查看stacktrace报告here
有人可以帮我解决这个性能问题。?
答案 0 :(得分:5)
首先,您应该在 DEBUG 中运行您的应用。在Android上,它通过更改MainApplication
方法:
@Override
public boolean getUseDeveloperSupport() {
return false; // BuildConfig.DEBUG;
}
制作捆绑包:
react-native bundle --platform android --dev false --entry-file ./index.js --bundle-output ./android/app/src/main/assets/index.android.bundle --assets-dest ./android/app/src/main/res/ --sourcemap-output ./android/app/src/main/assets/index.android.map
至于代码,这里有一些优化react-native的建议:
response.json()
或JSON.stringify
)阻止js线程,因此所有JS动画和处理程序(例如onScroll
和onPress
,当然{ {1}}方法)受此影响。尝试仅加载您需要显示的内容。render
参数),尽量不要使用useNativeDriver: true
。onScroll
方法,并尝试尽可能少地调用这些方法。当组件的道具或状态发生变化时调用它。render
的工作原理并尝试在必要时使用它。但请记住,如果使用不当,它也会降低应用程序的速度。PureComponent
,它会兑换它们并替换为样式ID(整数)。为:
StyleSheet
好:
// style object is created on every render
render() {
return <View style={{flex:1}}/>
}
为:
render() {
<View style={styles.flex}/>
}
// style is created once
const styles = StyleSheet.create({
flex: { flex: 1 }
});
好:
// onPress handler is created on every render
render() {
<TouchableOpacity onPress={() => this.props.navigator.navigate('SignIn')}/>
}
render() {
<TouchableOpacity onPress={this.onPressSignIn}/>
}
// onPressSignIn is created once
onPressSignIn = () => {
this.props.navigator.navigate('SignIn');
}
和Object
代替Set
。当您需要从服务器/数据库加载大量数据时,请使用分页,为服务器留下排序和其他繁重的计算。例如,如果您经常需要通过id获取对象,最好使用:
Array
而不是通常的数组:
let items = {
"123": { id: "123", ... },
"224": { id: "224", ... }
};
let item = items["123"];
答案 1 :(得分:4)
这是一个非常广泛和基于意见的问题,但我会尝试突出显示基于most common points
的{{1}}和建议你已经列出了。
查看堆栈跟踪,主要问题在于包名称中的profiler
,即UI Thread
。
如上所述here。
为了显示一个框架,我们所有的UI工作都需要在16ms周期结束时完成。
一旦边界间隔设置为com.fitspot.app.debug
,您就可以看到16ms
或mqt_js
在一个周期内花费的时间远远超过JS Thread
,这意味着16ms
一直在运行。
在当前JS Thread
中,不清楚profiler
中执行了哪些流程,因此很明显问题主要在于您的JS Thread
,而不是JS Code
}。
有多种方法可以加快UI Thread
应用的速度,这在page中有详细记录。这是一个基本要点。
react-native
模式下提供,您可以在整个应用中停用它们,以获得更好的效果。从您的应用中删除所有dev=true
语句,因为它会在JS主题上导致bottleneck
。您可以使用此插件删除.babelrc文件中提到的所有console.log
语句here
console*
您需要{
"env": {
"production": {
"plugins": ["transform-remove-console"]
}
}
}
项目结构,并使用componentize
,仅依靠Pure Components
和props
,更快地使用state
比较。
对于immutable data structures
,您可能需要检查slower navigation transitions
代码,因为他们大多数navigation library
代表timeout
。作为解决方法,您可以考虑构建自己的default transitions
。
如果您在代码库中使用transitioner
,则可以考虑设置Animations
,这会减少nativeDriver=true
的负担。这里有一个很好的解释example。
您还可以查看分析,查看JS thread
和JS Thead
操作,在此页面上有详细说明。
其他内容包括,不是Main Thread
模块,这不是必需的,仅导入所需的requiring/importing
,而不是classes
。
此外,您不需要whole component
制作external libraries
,因为它们的效果比simple UI components
的原生元素要慢得多。您可以考虑使用styled-components
对您的react-native
答案 2 :(得分:3)
在Scrollview上使用Flatlist:
initialNumToRender={number}
道具添加到Flatlist,因为它只显示屏幕上可见的组件并分离其他组件在Flatlist renderItem中使用PureComponent(在你的情况下,它将是每张卡片),这样它们只会在道具改变时呈现。
检查您的组件是否一次又一次地重新渲染,以便在render()或ComponentWillRecieveProps中测试put控制台,如果发生这种情况,则使用ShouldComponentUpdate。
从render()和ComponentWillRecieveProps中删除console.log。
进行这些更改,您会发现您的表现比以前好多了。
答案 3 :(得分:2)
可能有各种原因导致本机反应速度变慢。我建议以下关键点可以提供帮助:
dumb components
超过class components
。 redux
,它是一个功能强大的状态管理工具,如果正确实施,可以为您提供最佳代码。 react-monocole
和appr
等工具。 react-monocole。答案 4 :(得分:1)
如果mqt_js
是性能问题的主要原因,那就意味着在每次点击时,您的应用的JS线程都会有太多事情要做。 JS业务逻辑和底层本机领域之间的通信是异步完成的,当按下按钮时需要在JS端完成的操作越多,应用程序就越慢。
redux
的使用情况。如果您的应用的数据流主要使用redux
完成,那么您可以检查以下内容:
如果在每个点击事件中发生了太多的redux操作,请尝试删除不必要的操作,或者先确定触发重要动画的操作的优先级,然后在新的RN组件完成渲染后触发其他操作。您可以通过redux-logger
查看哪些操作属于最底层的操作。
将听取redux存储的组件分成较小的组件,每个组件都会监听存储的不同部分。因此,如果更新redux的商店,则只应重新呈现一小部分组件而不是一切。
使用记忆选择器处理经常更新的数据。在这种情况下,reselect可以为您提供帮助。