qiuxiang / react-native-amap3d

react-native 高德地图组件,使用最新 3D SDK,支持 Android + iOS
https://qiuxiang.github.io/react-native-amap3d/api/
MIT License
1.28k stars 329 forks source link

多个界面用到MapView,再次切换到首页MapView,操作(移动)地图时程序崩溃 #320

Open zhuzhengjing opened 6 years ago

zhuzhengjing commented 6 years ago

用到的版本package.json

{
  "name": "eTracking",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "test": "jest"
  },
  "dependencies": {
    "react": "16.2.0",
    "react-native": "0.52.3",
    "react-native-actionsheet": "^2.4.2",
    "react-native-amap3d": "^1.0.0-beta.1",
    "react-native-calendars": "^1.19.3",
    "react-navigation": "^2.0.1"
  },
  "devDependencies": {
    "babel-jest": "22.4.3",
    "babel-preset-react-native": "4.0.0",
    "jest": "22.4.3",
    "react-test-renderer": "16.3.1"
  },
  "jest": {
    "preset": "react-native"
  }
}

用了官方的react-navigation,只有一个界面集成MapView时没有问题,各种手势API调用都没有问题。

我这里是Main.js,代码如下:

import React, { Component } from 'react';
import { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { MapView } from 'react-native-amap3d';
import ActionSheet from 'react-native-actionsheet'

export default class Main extends Component {
  static navigationOptions = {
    title: '小翼',
  };

  state = {
    showsCompass: false,        // 是否显示罗盘
    zoomLevel: 18,              // 地图缩放级别,[3, 20]
    mapType: 'standard',        // standard: 标准地图,satellite: 卫星地图
    tiltEnabled: false,
    rotateEnabled: false,
    coordinate: {               // 定位模块当前位置
      latitude: 39.806901,
      longitude: 116.397972,
    },
  };

  locationType = ['离线模式', '省电模式', '普通模式', '性能模式', '休眠', '取消'];

  _coordinates = [
    {
      latitude: 39.806901,
      longitude: 116.397972,
    },
    {
      latitude: 39.806901,
      longitude: 116.297972,
    },
    {
      latitude: 39.906901,
      longitude: 116.397972,
    },
    {
      latitude: 39.706901,
      longitude: 116.397972,
    },
  ];

  // 改变定位模式
  _changeLocationType = () => {
    this._actionSheet.show();
  };

  _actionSheetSelected = (index) => {
    console.log(index, this.locationType[index]);
    switch (index) {
      case 0:
        break;
      default:
        break;
    }
  };

  // 地图缩放 [3, 20]
  // 放大
  _zoomIn = () => {
    console.log('zoom out', this.state.zoomLevel);
    if (this.state.zoomLevel === 20) {
      return;
    }
    let zoom = ++this.state.zoomLevel;
    this.setState({
      zoomLevel: zoom
    });
  };

  // 缩小
  _zoomOut = () => {
    console.log('zoom in', this.state.zoomLevel);
    if (this.state.zoomLevel === 3) {
      return;
    }
    let zoom = --this.state.zoomLevel;
    this.setState({
      zoomLevel: zoom
    });
  };

  // 标准地图,卫星地图
  _changeLocationStyle = () => {
    if (this.state.mapType === 'standard') {
      this.setState({
        mapType: 'satellite'
      });
    } else {
      this.setState({
        mapType: 'standard'
      });
    }
  };

  // 以定位模块当前位置为中心点
  _updateCurrentCenter = () => {
    this._mapView.animateTo({
      coordinate: {
        latitude: 39.806901,
        longitude: 116.397972,
      }
    });
  };

  // track history
  _enterTrackHistory = () => {
    this.props.navigation.push('History');
  };

  // 导航到设备
  _navigationToDevice = () => {
    console.log('_navigationToDevice');
  };

  render() {
    return (
      <View style={StyleSheet.absoluteFill}>
        <MapView
          {...this.state}
          ref={o => this._mapView = o}
          style={styles.mapView}
        >
          <MapView.Marker
            title={'小翼,电量95%'}
            centerOffset={{x:0, y:-56}}
            icon={() => (
              <View style={styles.customMarker}>
                <Image
                  style={{width: 80, height: 80}}
                  source={require('../res/small_coordinate_0.png')}
                />
              </View>
            )}
            coordinate={this._coordinates[0]}
          />
        </MapView>

        <View style={styles.toolView}>
          <TouchableOpacity
            onPress={this._changeLocationType.bind(this)}>
            <Image
              style={{width: 43, height: 43}}
              source={require('../res/quick_track-plus_0.png')}
            />
          </TouchableOpacity>
          <TouchableOpacity
            onPress={this._zoomIn.bind(this)}>
            <Image
              style={{width: 36, height: 34, marginTop: 20}}
              source={require('../res/zoom_in.png')}
            />
          </TouchableOpacity>
          <TouchableOpacity
            onPress={this._zoomOut.bind(this)}>
            <Image
              style={{width: 36, height: 34, marginTop: 1}}
              source={require('../res/zoom_out.png')}
            />
          </TouchableOpacity>
          <TouchableOpacity
            onPress={this._changeLocationStyle.bind(this)}>
            <Image
              style={{width: 44, height: 44, marginTop: 60}}
              source={require('../res/map_2d.png')}
            />
          </TouchableOpacity>
          <TouchableOpacity
            onPress={this._updateCurrentCenter.bind(this)}>
            <Image
              style={{width: 52, height: 52, marginTop: 10}}
              source={require('../res/location_0.png')}
            />
          </TouchableOpacity>
          <TouchableOpacity
            onPress={this._enterTrackHistory.bind(this)}>
            <Image
              style={{width: 33, height: 33, marginTop: 10}}
              source={require('../res/track_0.png')}
            />
          </TouchableOpacity>
        </View>
        <View style={styles.bottomView}>
          <View style={{width: 50, justifyContent: 'center', alignItems: 'center'}}>
            <Image
              source={require('../res/track_0.png')}
            />
          </View>
          <View style={{flex: 1}}>
            <Text style={{fontSize: 14, backgroundColor: 'red'}}>
              江苏省苏州市吴中区道浜村苏州创意产业园
            </Text>
            <Text style={{color: 'gray', fontSize: 12, top: 2}}>
              更新于13:59 GPS定位
            </Text>
          </View>
          <View style={{width: 50, justifyContent: 'center', alignItems: 'center'}}>
            <TouchableOpacity
              onPress={this._navigationToDevice.bind(this)}>
              <Image
                source={require('../res/going_0.png')}
              />
            </TouchableOpacity>
          </View>
        </View>
        <ActionSheet
          ref={o => this._actionSheet = o}
          title={'设定定位模式\n模式不一样,汇报间隔会有差别'}
          options={this.locationType}
          cancelButtonIndex={this.locationType.length - 1}
          destructiveButtonIndex={1}
          onPress={this._actionSheetSelected.bind(this)}
        />
      </View>
    )
  }
}

const styles = StyleSheet.create({
  mapView: {
    flex: 1,
    margin: 0,
    marginBottom: 68,
  },
  toolView: {
    position: 'absolute',
    top: 0,
    right:8,
    bottom: 68,
    width: 60,
    justifyContent: 'center',
    alignItems: 'center',
  },
  bottomView: {
    position: 'absolute',
    flexDirection: 'row',
    alignItems: 'center',
    left:0,
    right:0,
    bottom: 0,
    height: 68,
    width: '100%',
    backgroundColor: 'white',
  },
  customMarker: {
    alignItems: 'center',
    borderRadius: 5,
    padding: 5,
  },
  markerText: {
    color: '#fff',
  },
});

后面又写了History.js,通过react-navigation push了一个新实例,这里只绘制了一条路径。此时返回到Main.js时移动地图程序就崩溃了。

import React, { Component } from 'react';
import { StyleSheet, View, Text } from 'react-native';
import { MapView } from 'react-native-amap3d';

export default class History extends Component {
  static navigationOptions = {
    title: '历史轨迹',
  };

  state = {
    showsCompass: false,        // 是否显示罗盘
    zoomLevel: 18,              // 地图缩放级别,[3, 20]
    mapType: 'standard',        // standard: 标准地图,satellite: 卫星地图
    tiltEnabled: false,
    rotateEnabled: false,
    coordinate: {               // 定位模块当前位置
      latitude: 39.51000,
      longitude: 116.123,
    },
    linePoints: [
      {
        latitude: 39.51000,
        longitude: 116.123,
      },
      {
        latitude: 39.51110,
        longitude: 116.123,
      },
      {
        latitude: 39.51220,
        longitude: 116.123,
      },
      {
        latitude: 39.51350,
        longitude: 116.123,
      },
      {
        latitude: 39.51450,
        longitude: 116.1234,
      },
      {
        latitude: 39.51550,
        longitude: 116.1334,
      },
      {
        latitude: 39.50550,
        longitude: 116.1364,
      },
    ]
  };

  _onItemPress = point => {
    console.log((this._points.indexOf(point).toString()));
  };

  render() {
    return (
      <View style={StyleSheet.absoluteFill}>
        <MapView
          {...this.state}
          style={styles.mapView}
        >
          <MapView.Polyline
            gradient
            width={5}
            colors={['#f44336', '#2196f3', '#4caf50']}
            coordinates={this.state.linePoints}
          />
          <MapView.MultiPoint
            points={this.state.linePoints}
            onItemPress={this._onItemPress}
          />
        </MapView>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  mapView: {
    flex: 1,
    margin: 0,
    marginBottom: 68,
  },
});

截图如下,真机iPhone 6 Plus,模拟器iPhone X测试结果一致。崩溃前没有任何log。Xcode断点只定位到main函数,没有参考意义。看起来是内存问题。希望能帮忙看看,谢谢!

image

qiuxiang commented 6 years ago

看下崩溃时的调用栈

zhuzhengjing commented 6 years ago

image

zhuzhengjing commented 6 years ago

排除法,确定问题所在:去掉History.js中的MapView.MultiPoint就好了。

  render() {
    return (
      <View style={StyleSheet.absoluteFill}>
        <MapView
          {...this.state}
          style={styles.mapView}
        >
          <MapView.Polyline
            gradient
            width={5}
            colors={['#f44336', '#2196f3', '#4caf50']}
            coordinates={this.state.linePoints}
          />
          {/*<MapView.MultiPoint*/}
            {/*points={this.state.linePoints}*/}
            {/*onItemPress={this._onItemPress}*/}
          {/*/>*/}
        </MapView>
      </View>
    )
  }

MapView.MultiPoint 为什么会有这样的影响呢?

qiuxiang commented 6 years ago

不确定,能提供一个能重现的项目吗,方便直接调试

qiuxiang commented 6 years ago

应该不是 MultiPoint 的问题,不然 example 也会有问题的,看起来是在某种情况下才会导致的。单从你提供的代码看不出来。

zhuzhengjing commented 6 years ago

整理了一个最小demo,重现方法:首页点击jump跳转到第二页,随便操作地图几下,然后返回到首页,移动地图,程序崩溃。 @qiuxiang

https://github.com/brucehelen/rnamaptest

qiuxiang commented 6 years ago

好的,稍后看