背景
本人作为Android开发,以Android开发的角度记录一下集成RN,及和RN开发同事的配合需要做的事情。主要就是互相交互的问题。其实官方文档上已经说的很清楚啦,但是不够口语化,自己再叙述一边,加深一下印象。
JS调用原生的方法
官方举了一个JS调用原生类Toast的例子,在这里就照搬咯。在RN的世界,一般都是以Module为单位的。所以原生想提供一套具有关联性的方法,就应该把它归集成一个Module提供给JS。
编写Module类
1 | public class ToastModule extends ReactContextBaseJavaModule |
新建一个类,集成RN的类ReactContextBaseJavaModule,那么这个类就是一个可以为JS提供方法的Module啦。
1 |
|
在一个方法上加一个@ReactMethod注解,那么这个就是一个提供给JS调用的方法。JS那边调用的参数类型对应为:
下面的参数类型在@ReactMethod注明的方法中,会被直接映射到它们对应的JavaScript类型。
参数类型
Boolean -> Bool
Integer -> Number
Double -> Number
Float -> Number
String -> String
Callback -> function
ReadableMap -> Object
ReadableArray -> Array
再给这个Module起一个名字,复写ReactContextBaseJavaModule的getName方法,返回一个名字。JS里面就用这个名字调!
1 | Override |
到这儿Module就写完了,怎么提供给JS呢?
注册Module
原生模块注册Module给JS调用是以package为单位的。一组Module是一个package。这个package是什么呢?以什么类型存在呢?
React-Native提供了一个ReactPackage接口,接口里有个名为createNativeModules的方法,返回值为List
1 | public class TestUtilsPackage implements ReactPackage { |
Package写好了,完事具备,只欠注册。
还记得ReactInstanceManager吗?上篇blog里面有。
每个RN的界面(其实就是个view),有配有一个ReactInstanceManager。ReactInstanceManager生成的时候,就可以给它加上Package了。我们生成ReactInstanceManager的时候,使用的是建造者模式,ReactInstanceManager.builder().addPackage(new TestUtilsPackage())完成注册,后面JS就可以调用咯。
回调函数
官方文档上说,@ReactMethod注解的方法必须是一个void类型的。那么我们怎么把返回值反给JS呢?RN提供两个种回调方式
第一种:Callback
在@ReactMethod注解的方法上,参数列表末尾添加两个参数,Callback errorCallback,Callback successCallback,注意,这个Callback是com.facebook.react.bridge.Callback。
1 | package com.facebook.react.bridge; |
在@ReactMethod注解的方法里面回调callbabck的invoke方法就可以了。invoke是个可变参,参数类型参见上面的参数类型介绍。
第二种:Promise
该接口为com.facebook.react.bridge.Promise,把它作为最后一个参数,就可以使用了。
注意
- 不管是Callback,还是Promises,都只能调用一次,千万不要把它缓存起来多次调用!!!
- 夸语言的调用方式都是异步的。不管是Callback,还是Promises回调的时候,都是往消息循环中发送一条消息。
给JS发事件
1 | ... |
ReactContext对象可以从ReactInstanceManager中获取。
总结
原生和JS的互动,基本手段差不多就这些了。还有一个什么从startActivityForResult获取结果。感觉现在很少有人用吧?基本调用都很简单,但是要封装成能用的类库,供各个业务通用使用,还是需要有一些封装手段的。第一篇讲了原生集成RN环境的基本开发环境搭建,本篇说的是互相调用。计划再弄一篇,原生集成RN,原生端的代码需要怎么开发,还有基本原理。