React Native @rnmapbox/maps搭配react-navigation安卓跳转崩溃
@rnmapbox/maps 跨页面导航Android端崩溃异常
问题现象
- 使用
@rnmapbox/maps渲染地图页面时,执行跨页面跳转操作会先触发应用卡顿,随后直接崩溃 - 移除
<MapboxGL.MapView>标签内部所有子组件后,导航功能恢复正常,确认异常与Mapbox地图组件直接相关 - 项目使用
@react-navigation/native+@react-navigation/native-stack作为导航方案,异常仅在Android平台复现,iOS端全流程运行无任何问题 - 复现录屏:问题复现录屏
项目核心代码
App.js
import React from 'react'; import MapScreen from './src/screens/MapScreen'; import PlaceDetailsScreen from './src/screens/PlaceDetailsScreen'; import VideoPlayerScreen from './src/screens/VideoPlayerScreen'; import {createNativeStackNavigator} from '@react-navigation/native-stack'; import {NavigationContainer} from '@react-navigation/native'; import {SafeAreaProvider} from 'react-native-safe-area-context'; import {GestureHandlerRootView} from 'react-native-gesture-handler'; function App() { const Stack = createNativeStackNavigator(); return ( <SafeAreaProvider> <GestureHandlerRootView style={{flex: 1}}> <NavigationContainer> <Stack.Navigator> <Stack.Screen name="Map" component={MapScreen} options={{headerShown: false}} /> <Stack.Group> <Stack.Screen name="Details" component={PlaceDetailsScreen} /> <Stack.Screen name="VideoPlayer" component={VideoPlayerScreen} options={{headerShown: false}} /> </Stack.Group> </Stack.Navigator> </NavigationContainer> </GestureHandlerRootView> </SafeAreaProvider> ); } export default App;
MapScreen.js
import React, {useState, useRef, useMemo, useCallback, useEffect} from 'react'; import {View, Text, PermissionsAndroid, Platform} from 'react-native'; import MapboxGL from '@rnmapbox/maps'; import BottomSheet, {BottomSheetScrollView} from '@gorhom/bottom-sheet'; import Styles from '../../Styles'; import PlaceBtn from '../components/PlaceBtn/PlaceBtn'; import IconPin from './../assets/icons/icon-locationPin.svg'; MapboxGL.setAccessToken( 'XXXXXXXXXXXXXXXXXXXXXXXXXXX', ); function MapScreen({navigation}) { const [hasGeolocPermission, setHasGeolocPermission] = useState(false); const [currentRegion, setCurrentRegion] = useState([4.824, 45.76]); // 经度, 纬度 const [userLocation, setUserLocation] = useState(); const [nearestPoints, setNearestPoints] = useState([]); const markers = require('../data/markers.json'); const route = require('../data/route.json'); const routeLine = { type: 'FeatureCollection', features: [ { type: 'Feature', properties: {}, geometry: { type: 'LineString', coordinates: route.points, }, }, ], }; const bottomSheetRef = useRef(null); const snapPoints = useMemo(() => ['13%', '75%', '100%'], []); const handleSheetChanges = useCallback(index => { console.log('handleSheetChanges', index); }, []); const requestLocationPermission = async () => { if (Platform.OS === 'android') { try { const granted = await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION, ); if (granted === PermissionsAndroid.RESULTS.GRANTED) { console.log('location uses is granted'); setHasGeolocPermission(true); } else { console.log(granted); console.log('location access denied'); } } catch (error) { console.warn('error while request location : ', error); } } }; useEffect(() => { requestLocationPermission(); }, []); return ( <View style={Styles.container}> <MapboxGL.MapView style={Styles.map} scaleBarEnabled={false}> <MapboxGL.UserLocation animated showsUserHeadingIndicator minDisplacement={1} onUpdate={position => { console.log('position : ', position); }} /> <MapboxGL.Camera centerCoordinate={currentRegion} zoomLevel={14} /> {markers.map((marker, index) => { if (marker.category === 'introduction') { console.log('intro'); } else { return ( <MapboxGL.PointAnnotation key={index} id={marker.id + ''} coordinate={[marker.longitude, marker.latitude]}> <IconPin width={35} height={35} fill={'#00c0aa'} /> </MapboxGL.PointAnnotation> ); } })} <MapboxGL.ShapeSource id="line1" shape={routeLine}> <MapboxGL.LineLayer id="linelayer1" style={{lineColor: 'red', lineWidth: 5}} /> </MapboxGL.ShapeSource> </MapboxGL.MapView> <BottomSheet ref={bottomSheetRef} handleIndicatorStyle={Styles.handleIndicator} index={0} snapPoints={snapPoints} onChange={handleSheetChanges}> <View style={Styles.bottomSheetContent}> <Text style={Styles.bottomSheetTitle}>{route.name}</Text> <BottomSheetScrollView> {markers.map((place, index) => { return ( <PlaceBtn place={place} navigation={navigation} //isNear={nearestPoints.includes(place.id)} /> ); })} </BottomSheetScrollView> </View> </BottomSheet> </View> ); } export default MapScreen;
PlaceDetailsScreen.js
import React from 'react'; import {View, Text, TouchableOpacity} from 'react-native'; function PlaceDetailsScreen({navigation}) { return ( <> <TouchableOpacity style={{backgroundColor: '#00FF00'}} onPress={() => navigation.navigate('Map')}> <Text>返回地图页</Text> </TouchableOpacity> <TouchableOpacity style={{backgroundColor: '#00FF00'}} onPress={() => navigation.navigate('VideoPlayer')}> <Text>跳转视频播放页</Text> </TouchableOpacity> </> ); }
内容的提问来源于stack exchange,提问作者K1000
相关产品推荐
相关产品推荐

