继续rn学习,由于rn在android端的组件还不足,之前使用了一个第三方的图片选择库。其本身也是个学习rn Native module的好例子。接下来看看如何根据自己需求来定义Native Module。这里以自定义一个dialog模块为例。
1. 一个module需要继承ReactContextBaseJavaModule类,并实现其几个主要方法:
public class MyNativeModule extends ReactContextBaseJavaModule {
final String NO_CANCEL = "NO_CANCEL";
final String CAN_CANCEL = "CAN_CANCEL";
private boolean CANCELABLE = false;
private final Activity mMainActivity;
private final ReactApplicationContext mReactContext;
private Callback callback;
private String title = "title";
public MyNativeModule(ReactApplicationContext reactContext,Activity mainActivity){
super(reactContext);
this.mReactContext = reactContext;
this.mMainActivity = mainActivity;
}
@Override
public String getName(){
return "MyNativeModule";
}
@Override
public Map<String,Object> getConstants(){
final Map<String,Object> constants = new HashMap<>();
constants.put(NO_CANCEL,false);
constants.put(CAN_CANCEL,true);
return constants;
}
@ReactMethod
public void show(ReadableMap params,Callback callBack){
if(params.hasKey("cancelable") && params.getBoolean("cancelable"))
CANCELABLE = true;
else
CANCELABLE = false;
String t = params.getString("title");
if(params.hasKey("title") && t != null)
title = t;
else{
//no title
}
ReadableArray list = params.getArray("items");
this.callback = callBack;
String data[] = null;
if(list != null) {
data = new String[list.size()];
int i = 0;
for (; i < list.size(); i++) {
data[i] = list.getString(i);
}
}
ListDialog dialog = new ListDialog(mMainActivity,mMainActivity,data);
dialog.show();
}
}
首先是其getName方法,该方法返回组件的名称,需要与jsx中调用组件时名称一致。 其次,Map方法可以定义组件的一些静态数值,如Toast.LENGTH_SHORT。 还有就是自定义的调用方法,这类方法需要定义为 @ReactMethod。 2. jsx到Java传输数据需要遵循一定规范: Boolean -> Bool Integer -> Number Double -> Number Float -> Number String -> String Callback -> function ReadableMap -> Object ReadableArray -> Array 3. 若需要回传数据,可以通过回调实现。又jsx中传入方法,callback接收并执行(注:*回调方法只能执行一次*):
callback.invoke(...params);
4. 实现需要弹出的dialog功能:
class ListDialog extends Dialog{
private String[] itemData;
private Activity mActivity;
private ListView lv;
private boolean hasCallBack = false;
public ListDialog(Context context)
{
super(context);
}
public ListDialog(Context context,Activity activity){
super(context);
this.mActivity = activity;
}
public ListDialog(Context context,Activity activity,String [] data){
super(context,R.style.dialog);
this.mActivity = activity;
this.itemData = data;
View v = LayoutInflater.from(mActivity).inflate(R.layout.list_dialog,null,false);
lv = (ListView) v.findViewById(R.id.list_dialog);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(mActivity,R.layout.item_dialog_simple);
for (int i = 0; i < itemData.length; i++)
{
adapter.add(itemData[i].toString());
}
lv.setAdapter(adapter);
setContentView(v);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent,View view,int position,long id) {
doCallBack(position);
}
});
//getWindow().setWindowAnimations();
boolean cancelable = false;
setCanceledOnTouchOutside(CANCELABLE);
setTitle(title);
getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
private void doCallBack(int position){
if(!hasCallBack) {
this.hasCallBack = true;
WritableMap params = Arguments.createMap();
params.putInt("itemID",position);
callback.invoke(false,params);
this.cancel();
}
}
}
通过一个简单的内部类实现一个dialog展示。
5. 完成组件的注册:
public class MyModulePackage implements ReactPackage { private final Activity mMainActivity; private MyNativeModule myNativeModule; public MyModulePackage(Activity mMainActivity){ this.mMainActivity = mMainActivity; } @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactApplicationContext){ List<NativeModule> modules = new ArrayList<>(); modules.add(new MyNativeModule(reactApplicationContext,mMainActivity)); return modules; } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); } @Override public List<Class<? extends JavaScriptModule>> createJSModules() { return Collections.emptyList(); } }
主要实现其createNativeModules方法,加入自定义组件。
在MainActivity中添加该组件:
.addPackage(new MyModulePackage(MainActivity.this))
6. 最后在jsx中require一下该组件,就可以直接使用了。
var MyNativeModule = require('NativeModules').MyNativeModule;
...
MyNativeModule.show(params,(didCancel,response) => {
if(!didCancel){
if(response.itemID < params.items.length - 1)
ToastAndroid.show("showDialog -> " + response.itemID,ToastAndroid.SHORT);
else
ToastAndroid.show("cancel",ToastAndroid.SHORT);
}
});