React Native调用Android原生方法
16lz
2021-01-24
当有时候RN项目需要访问原生的api但是rn官方并还没封装这个模块时,就需要使用自己去手动封装。调用Android原生代码,以最简单的弹Toast为例:
-
定义ReactContextBaseJavaModule模块
- 首先在android的目录下定义一个类去继承ReactContextBaseJavaModule类,实现getName方法。此方法返回的参数就是你使用js调用的模块名。
- 根据自己的需求选择是否去重写getConstants方法,这个方法的作用是给js提供一些常量使用,通过map的键值去存储,map的键是js调用的名称,key是对应的值。
- 然后就是定义你对js提供的方法,对js提供的方法必须是没有返回值的,如果需要有返回值的话,则需要增加Callback参数,js通过callback获取函数需要返回的值。需要注意的是必须在方法上面加上@ReactMethod注解,才能让js识别调用。具体代码如下:
/** * 原生模块 */public class ToastModule extends ReactContextBaseJavaModule { private static final String DURATION_SHORT_KEY = "SHORT"; private static final String DURATION_LONG_KEY = "LONG"; public ToastModule(ReactApplicationContext reactContext) { super(reactContext); } /** * * @return js调用的模块名 */ @Override public String getName() { return "ToastModule"; } /** * 给rn定义模块的一些常量 * @return 常量的一些键值 */ @Nullable @Override public Map getConstants() { final Map constants = new HashMap<>(); constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT); constants.put(DURATION_LONG_KEY, Toast.LENGTH_LONG); return constants; } /** * 使用ReactMethod注解,使这个方法被js调用 * @param message 文本 * @param duration 时长 */ @ReactMethod public void show(String message, int duration, Callback success,Callback error) { try { Toast.makeText(getReactApplicationContext(), message, duration).show(); success.invoke("success"); } catch (Exception e){ error.invoke("error"); } }}
- 定义好模块之后,接下来就需要去注册模块。非常简单,定义一个类去实现,ReactPackage接口。这个接口只有两个方法,createViewManagers他是注册需要被调用原生控件的(下篇文章会讲到),createNativeModules就是注册原生方法需要实现的,他的返回值是个list,创建一个list然后把你之前定义的ReactContextBaseJavaModule添加进去就好。代码如下。
public class ToastReactPackage implements ReactPackage { /** * * @param reactContext 上下文 * @return 需要调用的原生控件 */ @Override public List createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); } /** * * @param reactContext 上下文 * @return 需要调用的原生模块 */ @Override public List createNativeModules( ReactApplicationContext reactContext) { List modules = new ArrayList<>(); modules.add(new ToastModule(reactContext)); return modules; }}
- 把上一步定义好的ReactPackage模块在application下注册。原生这边所有的工作就已经结束。
public class MainApplication extends Application implements ReactApplication { private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override public boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; } @Override protected List getPackages() { return Arrays.asList( new MainReactPackage(), new ToastReactPackage()//新添加需要注册的模块 ); } };
- 原生端工作已完成。接下来就是js端,只需要加载NativeModules模块,
从NativeModules中获取之前定义的ReactContextBaseJavaModule对应的getName的值就可以调用对应的方法了,具体如下:
import React, {Component} from 'react';import { AppRegistry, StyleSheet, Text, View, NativeModules} from 'react-native';export default class RNDemo extends Component { _toast(){ NativeModules.ToastModule.show('toast', NativeModules.ToastModule.SHORT,(success)=>{alert(success)},(error)=>{alert(error)}) } render() { return ( Welcome to React Native! ); }}const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', },});AppRegistry.registerComponent('RNDemo', () => RNDemo);
更多相关文章
- android仿iPhone滚轮控件实现及源码分析(二)
- 采用回调Activity的形式创建AlertDialog单选列表框
- Activity的启动流程分析
- Android获取控件宽高的几种方式
- android内核编译方法[转贴]
- Android对话框Dialog,PopupWindow,Toast的实现机制
- 2011年Android(安卓)Binder机制学习笔记之一
- Android的Touch事件处理和手势
- android发送模拟按键消息,出现死锁,timeout的解决方法