react native 之雙向通訊小tips
阿新 • • 發佈:2019-01-05
react natvie 與android 之間的通訊
在上述沒講全一些常見需求的實現。
- 例如 js與native 自定義事件的通訊等 由於 暴露給js的檢視 是繼承SimpleViewManager 只提供了暴露了屬性給js 設定
- 又比如js的檢視 渲染給native 的載入
js呼叫native 檢視的方法 實現
public abstract class XXXManager<T extends XXXView> extends ViewGroupManager<T> {
private static final String CLEAR = "clear" ;
private static final int CLEARTAG = 1;
private static final String REFRESH="refresh";
private static final int REFRESHTAG=2;
public T mView;
@ReactProp(name = "data")
public abstract void setData(T view, ReadableArray array);
//自定義了四個事件,native 傳送給js的
@Nullable
@Override
public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
MapBuilder.Builder<String, Object> builder = MapBuilder.builder();
builder.put("onTranslate", MapBuilder.of("registrationName", "onTranslate"));
builder.put("onScale", MapBuilder.of("registrationName" , "onScale"));
builder.put("onValueSelect", MapBuilder.of("registrationName", "onValueSelect"));
builder.put("onNothingSelect", MapBuilder.of("registrationName", "onNothingSelect"));
return builder.build();
}
public void clear() {
if (mView==null)return;
mView.clear();
}
public void refesh(){
if (mView==null)return;
mView.invalidate();
}
@Nullable
@Override
public Map<String, Integer> getCommandsMap() {
Map<String, Integer> map = new HashMap<>();
map.put(CLEAR, CLEARTAG);
map.put(REFRESH,REFRESHTAG);
return map;
}
//收到js傳送給native的資訊
@Override
public void receiveCommand(T root, int commandId, @Nullable ReadableArray args) {
switch (commandId) {
case CLEARTAG:
clear();
break;
case REFRESHTAG:
refesh();
break;
}
}
}
native 傳送訊息 例如傳送onScale 在上面註冊了
private void test(){
WritableMap event = Arguments.createMap();
event.putDouble("scaleX", scaleX);
event.putDouble("scaleY", scaleY);
setJSMEssage("onScale", event);
}
private void setJSMEssage(String funName, WritableMap event) {
ReactContext reactContext = (ReactContext) getContext();
reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
getId(),
funName,
event);
}
js端 接受事件
<XXXView
....
onScale={(event)=>console.log('onTranslated',event.nativeEvent)}
/>
js傳送事件
refresh(){
let r = this.ref.getRef()
UIManager.dispatchViewManagerCommand(
ReactNative.findNodeHandle(r),
//refresh 就是getCommandsMap 和receiveCommand 註冊的資訊
UIManager.XXXX.Commands.refresh,
null
)
}
react 的檢視給native 渲染
常見需求,例如 原生暴露的事件給js 端,但是 又部分 檢視不需要本地些死 而是暴露介面給上層,例如 地圖的mark 自定義mark是js端根據需求自定義 給native 地圖元件渲染,又例如 下拉重新整理 控制元件的頭部等
實現
我們先封裝一個自定義View給js
public class MarkView extends ReactViewGroup{
public MarkView(Context context) {
super(context);
}
public int width;
public int height;
}
將這個檢視暴露給js
public class MarkManager extends ViewGroupManager<MarkView> {
public static final String REACT_CLASS = "MarkView";
@Override
public String getName() {
return REACT_CLASS;
}
@Override
protected MarkView createViewInstance(ThemedReactContext reactContext) {
return new MarkView(reactContext);
}
}
//js呼叫 這裡是view是native 封裝好的檢視給js 然後在裡面新增自定義的markView 給native 渲染
<XXXView
...
onScale={(scaleX, scaleY) => {
console.log(scaleX, scaleY, '=========== onScale BarChartView.js')
}}
>
{this.renderMarkView()}
</XXXView>
)
}
renderMarkView () {
return (
<MarkView style={{ width: 50, height: 50, backgroundColor: '#0f0' ,justifyContent:'center',alignItems:'center'}} offset={{posx:0,posy:-100}}>
<Text>ssss</Text>
</MarkView>
)
}
//在我們剛才的xxxManager做處理
public abstract class XXXManager<T extends XXXView> extends ViewGroupManager<T> {
private static final String CLEAR = "clear";
private static final int CLEARTAG = 1;
private static final String REFRESH="refresh";
private static final int REFRESHTAG=2;
public T mView;
@Override
public void addView(T parent, View child, int index) {
if (child instanceof MarkView) {
//這裡已經接受了這個child 然後 你想幹嘛就幹嘛 注意這裡的addView 並沒有新增到裡面 需要自己邏輯處理是否addView
parent.setMark((MarkView) child,index);
}
}
}