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

启动React Native Activity时如何传参?Android订单详情跳转问题

嘿,我之前也踩过这个ReactContext为空的坑!你遇到的问题本质是React Native的初始化是异步的,Activity生命周期回调触发时,RN的上下文还没准备好,所以直接拿肯定是null。给你几个实用的解决方案,按需选就行:

方案一:通过Intent传数据,等RN初始化完成后再传递到JS

先把订单数据通过Intent传到React Native Activity,然后监听RN实例初始化完成的事件,拿到有效的ReactContext后再把数据发送给JS端。

Android端代码(ReactNativeActivity):

public class MyReactActivity extends ReactActivity implements ReactInstanceManager.ReactInstanceEventListener {
    private String mOrderId;
    private ReactInstanceManager mReactInstanceManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 先从Intent里取出订单ID
        mOrderId = getIntent().getStringExtra("ORDER_ID");
        
        // 获取React实例管理器,并添加初始化监听
        mReactInstanceManager = getReactNativeHost().getReactInstanceManager();
        mReactInstanceManager.addReactInstanceEventListener(this);
    }

    @Override
    public void onReactContextInitialized(ReactContext reactContext) {
        // 这里ReactContext终于可用了!把订单ID发送给JS
        reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit("onOrderDataReceived", mOrderId);
        
        // 记得移除监听,避免内存泄漏
        mReactInstanceManager.removeReactInstanceEventListener(this);
    }

    @Override
    protected String getMainComponentName() {
        return "YourRNComponentName"; // 替换成你的RN主组件名
    }
}

JS端监听事件:

import { NativeEventEmitter, NativeModules } from 'react-native';
import { useNavigation } from '@react-navigation/native';

const OrderDetailScreen = () => {
    const navigation = useNavigation();
    const eventEmitter = new NativeEventEmitter(NativeModules.DeviceEventManagerModule);

    useEffect(() => {
        const subscription = eventEmitter.addListener('onOrderDataReceived', (orderId) => {
            // 拿到订单ID后,就可以加载详情数据或者做页面跳转了
            console.log('收到订单ID:', orderId);
            // 示例:如果当前就是详情页,直接用orderId请求数据
            // fetchOrderDetail(orderId);
        });

        return () => subscription.remove(); // 组件卸载时移除监听
    }, []);

    return (
        // 你的详情页UI
    );
};

export default OrderDetailScreen;

方案二:自定义Native Module存储数据

通过自定义的React Native Module来暂存订单数据,等RN初始化完成后,JS端主动从Module里取数据。

自定义OrderDataModule:

public class OrderDataModule extends ReactContextBaseJavaModule {
    private String mCurrentOrderId;

    public OrderDataModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    @Override
    public String getName() {
        return "OrderDataModule"; // JS端调用时的模块名
    }

    // 给Android端设置订单ID的方法
    public void setOrderId(String orderId) {
        this.mCurrentOrderId = orderId;
    }

    // 给JS端提供的获取订单ID的方法
    @ReactMethod
    public void getOrderId(Promise promise) {
        promise.resolve(mCurrentOrderId);
    }
}

在CustomPackage里注册Module:

public class CustomPackage implements ReactPackage {
    @NonNull
    @Override
    public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new OrderDataModule(reactContext));
        return modules;
    }

    // 其他必要方法实现...
    @NonNull
    @Override
    public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

MainActivity中启动RN Activity时传递数据:

// RecyclerView点击事件里的逻辑
String targetOrderId = "你拿到的订单ID";
Intent intent = new Intent(MainActivity.this, MyReactActivity.class);
intent.putExtra("ORDER_ID", targetOrderId);
startActivity(intent);

ReactNativeActivity中设置数据到Module:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    String orderId = getIntent().getStringExtra("ORDER_ID");
    
    // 监听RN初始化完成,再把数据设置到Module
    getReactNativeHost().getReactInstanceManager().addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
        @Override
        public void onReactContextInitialized(ReactContext reactContext) {
            OrderDataModule module = reactContext.getNativeModule(OrderDataModule.class);
            module.setOrderId(orderId);
            getReactNativeHost().getReactInstanceManager().removeReactInstanceEventListener(this);
        }
    });
}

JS端获取数据:

import { NativeModules } from 'react-native';
import { useEffect, useState } from 'react';

const { OrderDataModule } = NativeModules;

const OrderDetailScreen = () => {
    const [orderId, setOrderId] = useState(null);

    useEffect(() => {
        OrderDataModule.getOrderId()
            .then(id => {
                if (id) {
                    setOrderId(id);
                    // 加载订单详情
                    // fetchOrderDetail(id);
                }
            })
            .catch(err => console.error('获取订单ID失败:', err));
    }, []);

    return (
        // 渲染详情页
    );
};

export default OrderDetailScreen;

方案三:使用Deep Linking传递参数

通过自定义的URL Scheme来传递订单ID,这种方式更符合RN的跨平台特性,后续iOS端也可以复用逻辑。

配置AndroidManifest.xml:

给你的ReactNativeActivity添加intent-filter:

<activity
    android:name=".MyReactActivity"
    android:label="@string/app_name"
    android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
    android:windowSoftInputMode="adjustResize">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <!-- 自定义Scheme,比如myapp://orderdetail?orderId=xxx -->
        <data android:scheme="myapp" android:host="orderdetail" />
    </intent-filter>
</activity>

MainActivity中启动RN Activity:

String targetOrderId = "你拿到的订单ID";
Uri deepLinkUri = Uri.parse("myapp://orderdetail?orderId=" + targetOrderId);
Intent intent = new Intent(Intent.ACTION_VIEW, deepLinkUri);
startActivity(intent);

JS端解析Deep Link参数:

import { Linking } from 'react-native';
import { useEffect, useState } from 'react';

const OrderDetailScreen = () => {
    const [orderId, setOrderId] = useState(null);

    useEffect(() => {
        // 获取初始URL
        Linking.getInitialURL().then(url => {
            if (url) {
                parseDeepLink(url);
            }
        });

        // 监听后续的Deep Link跳转(比如APP在后台时被唤醒)
        const subscription = Linking.addEventListener('url', event => {
            parseDeepLink(event.url);
        });

        return () => subscription.remove();
    }, []);

    const parseDeepLink = (url) => {
        const { queryParams } = Linking.parse(url);
        if (queryParams.orderId) {
            setOrderId(queryParams.orderId);
            // 加载订单详情
            // fetchOrderDetail(queryParams.orderId);
        }
    };

    return (
        // 渲染详情页
    );
};

export default OrderDetailScreen;

为啥ReactContext在生命周期里为空?

简单说就是RN的初始化是异步的,Activity的onCreate、onStart这些方法执行时,RN的JavaScript环境还没加载完成,ReactContext自然还没创建出来。必须等ReactInstanceManager触发onReactContextInitialized回调后,才能拿到有效的上下文对象。

内容的提问来源于stack exchange,提问作者DCoder

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:21:40