启动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
相关产品推荐
相关产品推荐

