React-Native:调用(Android)Native方法
有的时候我们使用React Native无法满足一些使用特定场景,这个时候就需要使用原生的Android方法,比如一些耗时的写操作,操作数据库或者多线程操作等。React Native可以直接调用系统的API(java方法),实现JavaScript与java语言的通讯,如果React Native中没有满足我们需求的Api,可以封装原生的方法提供JavaScript调用。
JavaScript和java通信是通过bridge实现的,在java层和JavaScript层的bridge分别存有相同的一份模块配置表。Java与JavaScript相互通信时,通过bridge里的配置表将所调用模块方式转为{moduleID,methodID,args}的形式传递给处理层,处理层通过bridge里的配置表找到对应的方法执行,如果有callback,则回传给调用层,如果没有执行就结束。
我们通过JavaScript调用Toast的例子来看下,JavaScript如何调用Java代码的。
新建一个项目:
react-native init app
在android的项目目录下面新建一个类RNToastModule,此类需要继承ReactContextBaseJavaModule。
ReactContextBaseJavaModule
ReactContextBaseJavaModule是一个抽象类,是用来被JavaScript调用对象的父类,我们需要Override一些ReactContextBaseJavaModule的方法。
首先要Override getName()方法:
@Override public String getName() { return "RNToastAndroid"; }
这个方法的返回值就是JavaScript中调用的名称,比如我们命名为RNToastAndroid,在JavaScript中可以这样调用:
var {NativeModules}=require('react-native');var rnToastAndroid = NativeModules.RNToastAndroid;
在JavaScript可以这样调用:
rnToastAndroid.show("我的万能JS", function (args) { alert(args) });
最后我们定义一个React调用的方法:
@ReactMethod public void show(String msg, Callback callback){ Toast.makeText(getReactApplicationContext(),"Js调用显示原生传递的参数是:"+msg,Toast.LENGTH_LONG).show(); callback.invoke("RNToastModule 调用JS方法"); }
完整RNToastModule代码:
/******************************** Copyright (c)*********************************\**** (c) Copyright 2015, Allen, china, shanghai** All Rights Reserved**** ** **-----------------------------------版本信息------------------------------------** 版 本: V0.1****------------------------------------------------------------------------------********************************End of Head************************************\*/package com.app;import android.widget.Toast;import com.facebook.react.bridge.Callback;import com.facebook.react.bridge.ReactApplicationContext;import com.facebook.react.bridge.ReactContextBaseJavaModule;import com.facebook.react.bridge.ReactMethod;/** * 文 件 名: RNToastModule * 创 建 人: Allen * 创建日期: 17/1/2 23:17 * 邮 箱: AllenCoder@126.com * 修改时间: * 修改备注: */public class RNToastModule extends ReactContextBaseJavaModule{ public RNToastModule(final ReactApplicationContext reactContext) { super(reactContext); } @Override public String getName() { return "RNToastAndroid"; } @ReactMethod public void show(String msg, Callback callback){ Toast.makeText(getReactApplicationContext(),"Js调用显示原生传递的参数是:"+msg,Toast.LENGTH_LONG).show(); callback.invoke("RNToastModule 调用JS方法"); }}
这个使用了annotation定义的方式必须加上@ReactMethod。
这里的参数只能React Navive定义的参数。
注册ReactPackage
新建一个JsReactPackage类,继承ReactPackage。
/******************************** Copyright (c)*********************************\**** (c) Copyright 2015, Allen, china, shanghai** All Rights Reserved**** ** **-----------------------------------版本信息------------------------------------** 版 本: V0.1****------------------------------------------------------------------------------********************************End of Head************************************\*/package com.app;import com.facebook.react.ReactPackage;import com.facebook.react.bridge.JavaScriptModule;import com.facebook.react.bridge.NativeModule;import com.facebook.react.bridge.ReactApplicationContext;import com.facebook.react.uimanager.ViewManager;import java.util.ArrayList;import java.util.Collections;import java.util.List;/** * 文 件 名: JsReactPackage * 创 建 人: Allen * 创建日期: 17/1/2 22:34 * 邮 箱: AllenCoder@126.com * 修改时间: * 修改备注: */public class JsReactPackage implements ReactPackage { @Override public List createNativeModules(final ReactApplicationContext reactContext) { List modules = new ArrayList<>(); modules.add(new RNToastModule(reactContext)); return modules; } @Override public List> createJSModules() { return Collections.emptyList(); } @Override public List createViewManagers(final ReactApplicationContext reactContext) { return Collections.emptyList(); }}
JsReactPackage创建了一个NativeModule的List。把JsReactPackage的实例都添加进去提供给JavaScript层调用。
需要在Application中实例化。
首先实现新建一个ReactNativeHost的实例并添加RNJavaReactPackage的实例:
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override protected boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; } @Override protected List getPackages() { return Arrays.asList( new MainReactPackage(), //加入此处 new JsReactPackage() ); }};
JavaScript中调用
在JavaScript显示Toast:
'use strict';var {NativeModules}=require('react-native');var rnToastAndroid = NativeModules.RNToastAndroid;rnToastAndroid.show("我的万能JS", function (args) { alert(args) });
这样就完成了从JavaScript中直接调用了Java中定义的方法。
参考链接
- https://segmentfault.com/a/1190000004486024
- http://blog.csdn.net/yuetingzhuying/article/details/51944254
更多相关文章
- Android(安卓)UI开发 View自绘控件 分享
- Android(安卓)Activity之间切换出现短暂黑屏的处理方法
- android横竖屏切换(复制未整理)
- Android大图加载方法
- android 自定义View之SubmitView
- Android(安卓)开发杂记
- android:GLSurfaceView绘制bitmap图片及glViewport调整的效果
- android单元测试AndroidTestCase
- 重温Android四大组件(一)—Activity的生命周期