如何更快地使React Native移动应用程序?

Kis*_*ela 14 performance android stack-trace react-native redux

React Native移动应用程序在每次点击时都非常慢.我正在使用react本机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"
  }
Run Code Online (Sandbox Code Playgroud)

我在android工作室中使用stacktrace进行了分析,发现mqt_js是每次UI点击需要更多时间的原因之一.您可以在此处查看堆栈跟踪报告

任何人都可以帮我解决这个性能问题.

Ale*_*lov 8

首先,您不应该在DEBUG中运行您的应用程序。在android上,可以通过更改MainApplication方法来完成:

@Override
public boolean getUseDeveloperSupport() {
  return false; // BuildConfig.DEBUG;
}
Run Code Online (Sandbox Code Playgroud)

并制作捆绑包:

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
Run Code Online (Sandbox Code Playgroud)

至于代码,以下是一些优化本机反应的建议:

  1. 解析和序列化(例如response.json()JSON.stringify)会阻止js线程,因此所有JS动画和处理程序(例如onScrollonPress,当然还有render方法)都会遭受此困扰。尝试仅加载您需要显示的内容。
  2. useNativeDriver: true尽可能使用本机动画(参数),并尽量不要使用onScroll
  3. 记录所有render方法,并尝试尽可能少地调用这些方法。当组件的属性或状态更改时调用。
  4. 了解PureComponent工作原理,并在必要时尝试使用它。但是请记住,如果使用不正确,它也可能会使应用速度变慢。
  5. 始终StyleSheet用于样式,它将兑现并替换为样式id(整数)。

坏:

// style object is created on every render
render() {
    return <View style={{flex:1}}/>
}
Run Code Online (Sandbox Code Playgroud)

好:

render() {
    <View style={styles.flex}/>
}

// style is created once
const styles = StyleSheet.create({
    flex: { flex: 1 }
});
Run Code Online (Sandbox Code Playgroud)
  1. 与功能相同。

坏:

// onPress handler is created on every render
render() {
    <TouchableOpacity onPress={() => this.props.navigator.navigate('SignIn')}/>
}
Run Code Online (Sandbox Code Playgroud)

好:

render() {
    <TouchableOpacity onPress={this.onPressSignIn}/>
}

// onPressSignIn is created once
onPressSignIn = () => {
    this.props.navigator.navigate('SignIn');
}
Run Code Online (Sandbox Code Playgroud)
  1. 客户端上所有操作的大O应该保持不变。尽可能少地枚举数组。始终使用ObjectSet不是Array在可能的地方。当您需要从服务器/数据库加载大量数据,为服务器保留排序和其他繁重的计算时,请使用分页。

例如,如果您经常需要通过id获取对象,则最好使用:

let items = {
    "123": { id: "123", ... },
    "224": { id: "224", ... }
};

let item = items["123"];
Run Code Online (Sandbox Code Playgroud)

而不是通常的数组:

let items = [
    0: { id: "123", ... },
    1: { id: "224", ... }
];

let item = items.find(x => x.id === "123");
Run Code Online (Sandbox Code Playgroud)


Pri*_*dya 6

这是一个非常广泛基于意见的问题,但我将尝试most common points根据profiler您列出的内容重点强调这些问题和建议。

查看您的堆栈跟踪,主要问题在于UI Thread您的包名称内部,即com.fitspot.app.debug.

正如这里提到的。

为了显示一帧,我们所有的 UI 工作都需要在 16 毫秒结束时完成。

一旦边界间隔设置为16ms,那么您可以看到mqt_jsJS Thread花费的时间远远长于16ms一个周期,这意味着您JS Thread一直在运行。

目前profiler还不清楚你的进程执行了哪些进程JS Thread,因此很明显问题主要出在你的JS Code而不是UI Thread.

有多种方法可以使react-native应用程序更快,此页面中有详细记录。这是相同的基本要点。

  • 模式中提供了错误和警告消息dev=true,您可以在整个应用程序中禁用它们以获得更好的性能。
  • console.log从您的应用程序中删除所有语句,因为它会导致bottleneckJS 线程上的a 。你可以使用这个插件删除这里console*提到的所有语句,在你的 .babelrc 文件中作为

    {
      "env": {
      "production": {
      "plugins": ["transform-remove-console"]
      }
     }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 你需要componentize你的项目结构,并使用Pure Components, 来依赖props并且stateimmutable data structures用于更快的比较。

  • 对于slower navigation transitions,您可能需要检查navigation library代码,因为大多数情况下它们都有一个timeoutfor default transitions。作为一种解决方法,您可以考虑构建自己的transitioner.

  • 如果您Animations在代码库中使用,则可以考虑设置nativeDriver=true,这将减少JS thread. 这是一个很好解释的例子

  • 您可能还想检查Profiling,检查JS TheadMain Thread操作,在这个页面上有很好的解释。

  • 其他东西包括,不是requiring/importing模块,这是不必要的,只classes需要导入,而不是whole component.

  • 此外,您不需要external librariesmake simple UI components,因为它们的性能比react-native. 您可以考虑使用styled-components组件化您的UI


Raj*_*pta 4

  1. 在 Scrollview 上使用Flatlist

    • 将 prop添加initialNumToRender={number}到 Flatlist,因为它将仅显示屏幕上可见的组件并分离其他组件
  2. 在 Flatlist renderItem 中使用PureComponent(在您的情况下它将是 Each Card),这样它们只会在其 props 发生更改时才会渲染。

  3. 检查您的组件是否一次又一次地重新渲染,以便测试将控制台放入 render() 或 ComponentWillRecieveProps 中,如果发生这种情况,则使用 ShouldComponentUpdate。

  4. 从 render() 和 ComponentWillRecieveProps 中删除 console.log。

进行这些更改后,您会发现自己的表现比以前好得多。