如何在Expo原生模块中创建新的ReactRootView?
在Expo原生模块中渲染React Native组件到悬浮窗的解决方案
一、添加必要的原生依赖
在你的Expo原生模块的模块级build.gradle文件中,添加以下依赖,确保能获取React Native核心组件和react-native-paper的原生支持:
dependencies { // React Native核心库(版本需与你的Expo项目RN版本匹配) implementation "com.facebook.react:react-native:+" // react-native-paper的原生依赖 implementation project(':react-native-paper') // Expo模块核心依赖(确保已存在) implementation project(':expo-modules-core') }
二、通过Expo的ReactNativeHost获取ReactInstanceManager
Expo环境下不能直接实例化ReactRootView,需要借助Expo提供的ReactActivityProvider接口获取ReactInstanceManager,再创建并挂载你的JS组件。以下是悬浮窗服务的核心代码示例:
import com.facebook.react.ReactInstanceManager; import com.facebook.react.ReactRootView; import expo.modules.core.interfaces.ReactActivityProvider; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.view.WindowManager; public class FloatingChipService extends Service { private ReactRootView mReactRootView; private WindowManager mWindowManager; @Override public void onCreate() { super.onCreate(); // 从Expo应用上下文获取ReactInstanceManager ReactInstanceManager reactInstanceManager = ((ReactActivityProvider) getApplicationContext()).getReactNativeHost().getReactInstanceManager(); // 初始化ReactRootView并启动注册好的MyChip组件 mReactRootView = new ReactRootView(this); mReactRootView.startReactApplication( reactInstanceManager, "MyChip", // 对应JS端AppRegistry.registerComponent的组件名 null // 传递给组件的props,可根据需求传入 ); // 配置悬浮窗布局参数 WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, android.graphics.PixelFormat.TRANSLUCENT ); mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE); mWindowManager.addView(mReactRootView, layoutParams); } @Override public void onDestroy() { super.onDestroy(); if (mReactRootView != null) { mWindowManager.removeView(mReactRootView); mReactRootView.unmountReactApplication(); } } @Override public IBinder onBind(Intent intent) { return null; } }
三、确保JS组件正确注册
JS端的MyChip组件需通过AppRegistry.registerComponent完成注册,确保Android端能找到对应的组件:
import React from 'react'; import { AppRegistry } from 'react-native'; import { Chip } from 'react-native-paper'; const MyChip = () => { return ( <Chip icon="bell" onPress={() => {/* 处理点击逻辑 */}} style={{ backgroundColor: '#fff' }} > 后台悬浮Chip </Chip> ); }; // 注册组件,名称需与Android端startReactApplication传入的一致 AppRegistry.registerComponent('MyChip', () => MyChip); export default MyChip;
四、关键注意事项
- 悬浮窗权限:在
AndroidManifest.xml中声明<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />,并在运行时引导用户开启权限。 - 前台服务配置:确保你的服务已配置为前台服务,避免被系统回收。
- 版本一致性:确保原生模块依赖的React Native版本与你的Expo项目版本完全匹配,避免依赖冲突。
- 组件卸载:在服务销毁时务必移除
ReactRootView并调用unmountReactApplication,防止内存泄漏。
内容的提问来源于stack exchange,提问作者takanuva15
相关产品推荐
相关产品推荐

