第一部分,在ReactNative中,原生与js交互常用的是原生通过向js发送事件,参考webview源代码。
1、定义事件与发送消息方法
public class ReactExpandListViewEvent extends Event<ReactExpandListViewEvent> { public static final String EVENT_NAME = "topExpandListViewClick"; private WritableMap mEventData; public ReactExpandListViewEvent(int viewId, WritableMap eventData) { super(viewId); mEventData = eventData; } @Override public String getEventName() { return EVENT_NAME; } @Override public void dispatch(RCTEventEmitter rctEventEmitter) { rctEventEmitter.receiveEvent(getViewTag(), getEventName(), mEventData); } }2、注册事件(topExpandListViewClick) 在ViewManager重写以下方法 //注册事件(ReactExpandListViewEvent) @Override public Map<String, Object> getExportedCustomDirectEventTypeConstants() { return MapBuilder.<String, Object>builder() .put("topExpandListViewClick", MapBuilder.of("registrationName", "onExpandListViewClick")) .build(); }3、组装发送到js的数据在ViewManger中组装数据
//组装发送到js的数据 private WritableMap createExpandListViewEvent(ExpandableListView expandListView) { WritableMap event = Arguments.createMap(); event.putDouble("target", 2222222); event.putString("url", "22222"); event.putBoolean("loading", true); event.putDouble("width", expandListView.getWidth()); return event; }4、ViewManger发送事件给js public void emitExpandListViewEvent(ExpandableListView expandListView) { dispatchEvent(expandableListView, new ReactExpandListViewEvent(expandListView.getId(), createExpandListViewEvent(expandListView))); } //发送事件到js private static void dispatchEvent(ExpandableListView expandableListView, Event event) { ReactContext reactContext = (ReactContext) expandableListView.getContext(); EventDispatcher eventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher(); eventDispatcher.dispatchEvent(event); }5、js组件侦听 'use strict'; import React from 'react'; import { PropTypes } from 'react'; import ReactNative from 'react-native'; import { ViewPropTypes, StyleSheet, UIManager, View, requireNativeComponent, DeviceEventEmitter, } from 'react-native'; var RCT_EXPANDABLELISTVIEW_REF = 'expandableListView'; class ExpandableListView extends React.Component { static propTypes = { ...ViewPropTypes, layoutWidth: PropTypes.number, layoutHeight: PropTypes.number, }; render() { var expandableListViewStyles = [styles.container, this.props.style]; var expandableListView = <RCTExpandableListView ref={RCT_EXPANDABLELISTVIEW_REF} key="expandableListViewKey" style={expandableListViewStyles} onExpandListViewClick={this.onExpandListViewClick} />; return ( <View style={styles.container}> {expandableListView} </View> ); } goExpand = () => { //console.log("1111"); UIManager.dispatchViewManagerCommand( this.getExpandableListViewHandle(), UIManager.RCTExpandableListView.Commands.goExpand, null ); }; postMessageExpand = () => { UIManager.dispatchViewManagerCommand( this.getExpandableListViewHandle(), UIManager.RCTExpandableListView.Commands.postMessageExpand, null ); }; injectJavaScriptExpand = (data) => { UIManager.dispatchViewManagerCommand( this.getExpandableListViewHandle(), UIManager.RCTExpandableListView.Commands.injectJavaScriptExpand, [data] ); }; /** * We return an event with a bunch of fields including: * url, title, loading, canGoBack, canGoForward */ updateNavigationState = (event) => { if (this.props.onNavigationStateChange) { this.props.onNavigationStateChange(event.nativeEvent); } }; getExpandableListViewHandle = () => { return ReactNative.findNodeHandle(this.refs[RCT_EXPANDABLELISTVIEW_REF]); }; onExpandListViewClick = (event: Event) => { console.log("onExpandListViewClick------------->"+event.nativeEvent.url); var onExpandListViewClick = this.props.onExpandListViewClick; onExpandListViewClick && onExpandListViewClick(event); this.updateNavigationState(event); }; } var RCTExpandableListView = requireNativeComponent('RCTExpandableListView', ExpandableListView, {}); var styles = StyleSheet.create({ /* container: { flex: 1, }, */ }); module.exports = ExpandableListView;第二部分,js可以通过命令的形式来调用原生(先除掉调用原生方法与自定义组件)1、ViewManger重写以下方法,分为注册命令与接收js发送的命令
//注册命令 @Override public @Nullable Map<String, Integer> getCommandsMap() { return MapBuilder.of( "goExpand", COMMAND_GO_BACK, "postMessageExpand", COMMAND_POST_MESSAGE, "injectJavaScriptExpand", COMMAND_INJECT_JAVASCRIPT ); } //接收命令;js通过命令来操作(比如ReactNative页面上有个 // 前进按钮点击后可以触发这些命令) @Override public void receiveCommand(ExpandableListView root, int commandId, @Nullable ReadableArray args) { switch (commandId) { case COMMAND_GO_BACK: UiThreadUtil.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(activity, "hello", Toast.LENGTH_SHORT).show(); } }); break; case COMMAND_POST_MESSAGE: try { JSONObject eventInitDict = new JSONObject(); eventInitDict.put("data", args.getString(0)); Toast.makeText(activity,eventInitDict.toString(),Toast.LENGTH_SHORT); /* root.loadUrl("javascript:(function () {" + "var event;" + "var data = " + eventInitDict.toString() + ";" + "try {" + "event = new MessageEvent('message', data);" + "} catch (e) {" + "event = document.createEvent('MessageEvent');" + "event.initMessageEvent('message', true, true, data.data, data.origin, data.lastEventId, data.source);" + "}" + "document.dispatchEvent(event);" + "})();"); */ } catch (JSONException e) { throw new RuntimeException(e); } break; case COMMAND_INJECT_JAVASCRIPT: //root.loadUrl("javascript:" + args.getString(0)); break; } }2、js发送命令参考第一部分第五条js组件侦听中的方法goExpand等
具体代码可以参考Git:https://github.com/Springever/Test