You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 18:40:38