Expo托管应用Android端导航前崩溃问题求助
解决Android端导航前崩溃的问题
针对你遇到的Expo托管应用Android端在导航至目标页面前崩溃的问题,结合代码和现象,给出以下排查方向和解决方案:
1. 捕获所有异步操作异常
你的handlePayment是异步函数,但未对await调用添加完整的异常捕获逻辑。Android对未处理的Promise拒绝更为严格,即使你检查了response.ok,如果API调用抛出网络错误、超时等未返回响应的异常,会直接导致应用崩溃。
修改代码,将所有异步逻辑包裹在try/catch中:
const handlePayment = async () => { setLoading(true); try { const sessionResponse = await paymentApi.paymentSession( selected, route.params.transaction.id, cvv ); if (!sessionResponse.ok) { throw new Error(sessionResponse.data?.error || "Unexpected Error Occurred while creating session."); } console.log('create and update session', sessionResponse); if (sessionResponse.data.session.updateStatus === 'SUCCESS') { const initiateResponse = await paymentApi.initiateAuthentication( sessionResponse.data.session.id, route.params.transaction.id ); if (!initiateResponse.ok) { throw new Error(initiateResponse.data?.error || "Unexpected Error Occurred while initiating authentication"); } console.log('Initiate Authentication', initiateResponse.data); if (initiateResponse.data.result === 'SUCCESS') { setInitiateWebView(true); const redirectHTML = initiateResponse.data.authentication.redirectHtml.replace(/\/g, ''); setInitiateWebViewUrl(redirectHTML); console.log('session id ', sessionResponse.data.session.id); const authenticateResponse = await paymentApi.authenticatePayer( sessionResponse.data.session.id, route.params.transaction.id ); if (!authenticateResponse.ok) { throw new Error("Unexpected Error Occurred, Please try again"); } console.log('authenticate payer', authenticateResponse.data); const authenticationResponseData = authenticateResponse.data; console.log('authenticate payer authenticate data', authenticationResponseData.authentication); const payerInteraction = authenticationResponseData.authentication.payerInteraction; if (authenticationResponseData.authentication['3ds2']) { const status = authenticationResponseData.authentication['3ds2'].transactionStatus; if (payerInteraction === 'REQUIRED' && status === "C") { console.log("Challenge Flow"); setAuthenticateWebViewUrl(authenticationResponseData.authentication.redirectHtml.replace(/\/g, '')); console.log('Auth webview url::::::', authenticationResponseData.authentication.redirectHtml.replace(/\/g, '')); setLoading(false); if (Platform.OS === 'ios') { navigation.navigate(routes.PAYWITHTOKEN, { html: authenticationResponseData.authentication.redirectHtml.replace(/\/g, '') }); } else { navigation.navigate(routes.PAYWITHTOKENANDROID); } } } } } } catch (error) { setLoading(false); if (Platform.OS !== 'ios') { clearInterval(myInterval); } Alert.alert(error.message); } };
2. 避免在组件卸载后更新状态
调用navigation.navigate后,当前组件可能开始卸载,此时如果还有未完成的状态更新(如setLoading(false)),可能触发Android端崩溃。可以通过添加组件挂载标记来防止这种情况:
const handlePayment = async () => { let isMounted = true; setLoading(true); try { // ... 原有异步逻辑 ... if (payerInteraction === 'REQUIRED' && status === "C") { // ... 日志和状态设置 ... if (isMounted) { setLoading(false); if (Platform.OS === 'ios') { navigation.navigate(routes.PAYWITHTOKEN, { html: authenticationResponseData.authentication.redirectHtml.replace(/\/g, '') }); } else { navigation.navigate(routes.PAYWITHTOKENANDROID); } } } } catch (error) { if (isMounted) { setLoading(false); Alert.alert(error.message); } } finally { isMounted = false; } }; // 监听组件卸载,标记为已卸载 useEffect(() => { return () => { isMounted = false; }; }, []);
3. 延迟导航操作(临时 workaround)
Android端有时需要等待React完成状态更新后再执行导航,可以尝试用setTimeout延迟导航:
// 在Android分支中修改: setLoading(false); setTimeout(() => { navigation.navigate(routes.PAYWITHTOKENANDROID); }, 100);
4. 检查依赖版本兼容性
确保你的Expo SDK版本和@react-navigation/native等导航相关依赖是最新的,旧版本可能存在Android端导航特定的bug。
内容的提问来源于stack exchange,提问作者kd12345
相关产品推荐
相关产品推荐

