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

上一篇下一篇

猜你喜欢

热点阅读