RN调用原生视图填坑记录
2021-09-25 本文已影响0人
捉影T_T900
已有的APP是个什么状态?
当前已有的APP本质是一个纯原生的应用,用java代码实现的基础容器。
ReactNative充当一个什么角色?
由于历史原因,已有业务中ReactNative已经作为RN插件的形式在上层进行各种设备独立操作界面的渲染,实现针对各个设备的控制逻辑。
如果ReactNative插件想使用底层能力怎么办?例如相机、音视频编解码、数据库等重业务功能
使用RreactNative官方支持的和原生逻辑交互解决方案。通过
com.facebook.react.bridge
包下数据封装方法实现RN和原生层面的数据流转
准备工作
1、在Activity指定Package
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setJSBundleFile(path)
.setJSMainModulePath("ReactNative")
.addPackage(new DevicePackage())
.setUseDeveloperSupport(deugable)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
2、Package中指定NativeModule、ViewManager
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new LivePlayNativeModule(reactContext));
modules.add(new CloudPlayNativeModule(reactContext));
modules.add(new SDCardPlayNativeModule(reactContext));
return modules;
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList(
new LivePlayViewManager(),
new CloudPlayViewManager(),
new SDCardPlayViewManager()
);
}
3、NativeModule、ViewManager的对应关系和作用
NativeModule对应js文件内的js方法
通过 @ReactMethod 注解指定js、原生方法,返回数据使用 Promise 对象
ViewManager对应js文件中控件的属性、状态的回调
通过 @ReactProp(name = "videoPlayParam") 注解指定RN控件属性,属性值变化后会触发这个原生方法的调用
遇到的深坑
1、属性值是一个集合怎么在原生代码接收?
通过 ReadableMap 对象接收参数集合
@ReactProp(name = "videoPlayParam")
public void setVideoPlayParam(QHVCTextureView view, ReadableMap params)
2、关于js中被动接收原生上行数据
在ViewManager中,重写【addEventEmitters】方法,以及重写【getExportedCustomBubblingEventTypeConstants】方法
定义原生、js事件对应方法名称key
public static final String EVENT_NATIVE_PLAYERSTATUSCHANGE_NAME = "onNativePlayerStatusChange";
public static final String EVENT_JS_PLAYERSTATUSCHANGE_NAME = "onPlayerStatusChange";
getExportedCustomBubblingEventTypeConstants 中注册绑定原生、js对应方法。注意,!!!!phasedRegistrationNames, bubbled 这两个key为固定值!!!!!
@Override
public Map<String, Object> getExportedCustomBubblingEventTypeConstants() {
LogUtils.i(TAG, "getExportedCustomBubblingEventTypeConstants");
return MapBuilder.<String, Object>builder()
.put(EVENT_NATIVE_PLAYERSTATUSCHANGE_NAME,
MapBuilder.of("phasedRegistrationNames", MapBuilder.of("bubbled", EVENT_JS_PLAYERSTATUSCHANGE_NAME)))
.build();
}
向js写入回调数据
// 返回数据到RN
WritableMap dataMap = Arguments.createMap();
dataMap.putInt("playerStatus", playerStatus);
reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
view.getId(),
EVENT_NATIVE_PLAYERSTATUSCHANGE_NAME,
dataMap
);
js中接收返回的原生数据
//通过PropTypes来说明这个组件的接口
CloudPlayView.propTypes = {
/**
* 播放器状态回调
* 内容格式: {"playerStatus":1,"ratio":0.75}
* playStatus枚举如下:(ratio仅在playerStatus为1的情况下才有值)
* 0-视频流已准备好,默认自动播放
* 1-视频长宽比变化
* 2-视频第一帧绘制完成,应该隐藏loading蒙层
* 3-开始缓冲,应该显示loading蒙层
* 4-缓冲结束,应该隐藏loading蒙层
* 5-播放完成
*/
onPlayerStatusChange: PropTypes.func,
}
<RNCloudPlayView onPlayerStatusChange={this._onPlayerStatusChange} />
_onPlayerStatusChange = (event) => {
if (!this.props.onPlayerStatusChange) {
return;
}
//process raw event...
this.props.onPlayerStatusChange(event.nativeEvent);
}
done