如何将非静态,按需NativeModule注入React Native Android?

时间:2017-10-25 20:35:01

标签: javascript java android react-native kotlin

在混合应用中,多个Activity / Fragment实例嵌套自己的ReactRootView共享一个ReactInstanceManager实例,似乎没有正式方法可以注入每个Activity / Fragment实例的本机模块。本质上,本机模块是单独的,例如驻留在.js文件中的javascript模块。如果在同一Fragment的不同实例中运行的JS代码想要访问Java / Kotlin端以与Fragment的本地属性进行交互,则这不是预期的行为。

我尝试使用registerAdditionalPackages()的{​​{1}}方法,但如果多个ReactInstanceManager s / Fragment同时使用,则会失败并出现如下所示的断言错误。

Activity

这不是线程安全问题,而是"Extending native modules with non-matching application contexts."实现的设计结果。还有另一种方法,如果是这样,你如何访问JS方面注入的模块?

1 个答案:

答案 0 :(得分:0)

这个问题使我几天保持清醒。最后,我有一个解决方案。我希望它能帮助将来的某个人。解决方案在Kotlin中,但将其转换为Java非常简单。 registerAdditionalPackages()是一个“非空”断言,大写someVariable!!调用是实例创建,SomeObject()是继承或实现,SomeType:SomeOtherType是变量声明。其余的都一样。

步骤:

1)在您希望将模块注入RN运行时时运行以下代码。 val someVar:SomeTypeActivity.onCreate()内部是一些不错的候选人。 Fragment.onCreateView()是您的单身全局反应运行时。 mReactInstanceManager定义将在稍后给出。

packageToInject

2) synchronized(mReactInstanceManager!!.currentReactContext!!) { val nativeModuleRegistryBuilder = NativeModuleRegistryBuilder( mReactInstanceManager!!.currentReactContext as ReactApplicationContext?, mReactInstanceManager!!, false ) nativeModuleRegistryBuilder.processPackage(packageToInject) mReactInstanceManager!!.currentReactContext!!.catalystInstance!!.extendNativeModules(nativeModuleRegistryBuilder.build()) } 中的实例必须按照以下方式准备,以便为每个packageToInject / Fragment实例创建一个唯一名称的唯一模块。制作ActivityFragment

的内部课程
Activity

3)当您在class ReactManagerPackage : ReactPackage { override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> { return emptyList() } override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> { val modules = ArrayList<NativeModule>() modules.add(ReactBridge(reactContext)) return modules } } class ReactBridge(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { override fun getName(): String { return myFragmentOrActivity.hashCode().toString() } @ReactMethod fun showToast(text: String) { Toast.makeText(text, Toast.LENGTH_SHORT).show() } } myFragmentOrActivity.hashCode().toString()中启动mReactRootView.startReactApplication()时,将Activity.onCreate()作为道具传递。把它放在你给Fragment.onCreateView()作为第三个参数的包中。

mReactRootView.startReactApplication()

4)使用组件中的prop(本例中为val bundle = Bundle() bundle.putString("fragmentOrActivityHash", myFragmentOrActivity.hashCode().toString()) mReactRootView.startReactApplication(mReactInstanceManager, "MyRootComponent", bundle ) )来检索特定的桥。 (JavaScript)的

MyRootComponent

利润!