明天和意外你永远都不知道哪一个先来,编程界亦是如此。例如某个已经有原生代码开发模块的项目要求用RN扩张某些功能;又例如,RN中未封装到的组件非得求助于原生代码。所以RN与原生代码通讯对于混合编程是至关重要的。为了实现两者之间的通信,facebook也提供了三种通信方式。

看内容.jpg

RCTDeviceEventEmitter消息机制:由Native主导控制,可以任意时刻传递

Callback回调方式:由js代码调用,原生代码返回。

Promise机制方式:由js调用,只是每次使用都需要调用。

一、RN调用安卓代码(简单)

RN调用安卓原生的代码,大致分为如下几步。

1、用Android Studio打开一个已经创建好的RN项目,选择android/build.gradle文件。

01.jpg

2、创建一个类继承ReactContextBaseJavaModule,在该类中我们应该要暴露出一些让RN调用的方法,封装成一个原生模块。

新建一个类MyReactPackage继承ReactContextBaseJavaModule

02.jpg

public class MyNativeModule extends ReactContextBaseJavaModule{

}

实现getName方法。该方法用于返回RN代码需要寻找的类的名称。(alt+enter快捷键可快速实现父类方法)

@Override

public String getName() {

// 一定要有名字 RN代码要通过名字来调用该类的方法

return "ToastModule";

}

实现类的构造方法。在这里将传入的上下文赋值给类内部私有的上下文

// 创建一个上下文,放到构造函数中,得到reactContext

private ReactApplicationContext mContext;

public MyNativeModule(ReactApplicationContext reactContext){

super(reactContext);

mContext = reactContext;

}

创建暴露给RN调用的方法。但是要用注释符号@ReactMethod修饰。

//方法不能返回值 因为被调用的原生代码是异步的 原生代码执行结束之后只能通过回调函数或者发送消息给RN

@ReactMethod

public void rnCallNative(String msg){

//这个方法是说弹出一个弹窗到界面Toast.makeText(mContext,msg,Toast.LENGTH_LONG).show();

}

3、在原生代码中创建一个类实现接口ReactPackage包管理器,并且把第二步已经创建好的类加入到原生模块列表里。

实现接口ReactPackage的方法,当然我们现在只需要创建模块,所以在其他的实现先直接返回空集合即可。而在createNativeModules方法中,要先声明一个装有原生模块的列表。之后将原生模块加入到列表里。

public class MyReactPackage implements ReactPackage {

@Override

public List createNativeModules(ReactApplicationContext reactContext) {

List modules = new ArrayList<>();

modules.add(new MyNativeModule(reactContext));

return modules;

}

@Override

public List createViewManagers(ReactApplicationContext reactContext) {

return Collections.emptyList();

}

}

4、将创建好的包管理器添加到ReactPackage列表里,也就是MainApplication代码中

在类里找到方法getPackages方法,将包管理器添加进去。

@Override

protected List getPackages() {

return Arrays.asList(

new MainReactPackage(),

new MyReactPackage()

);

}

5.在RN代码中用NativeModules组件去调用原生模块

导入组件

import {

AppRegistry,

StyleSheet,

Text,

View,

NativeModules,

} from 'react-native';

设置方法调用原生代码

call_button(){

NativeModules.ToastModule.rnCallNative('RN与安卓开发');

}

布置UI

在render方法里面设置当用户点击文字时,调用自定义的方法call_button。并且以这种形式创建的方法需要进行绑定

render() {

return(

测试原生通讯

);

}

处理好样式

const styles = StyleSheet.create({

container: {

flex:1,

backgroundColor:'deeppink',

flexDirection:'row',

justifyContent:'center',

alignItems:'center' },

});

至此,基本的RN调用安卓原生代码的方式就得以实现。再从RN的角度来回看整个过程。RN调用原生的方法,此时安卓的application就会启动,完成之后它会去找Package的列表,进而找到自己创建的列表。而在组件的列表里面有一个原生模块列表,到自己的模块列表里面调用模块里的方法就完成了调用。

效果图如下:

03.jpg

二、RN用消息机制方式与安卓原生代码切换

实现效果:在原生代码中添加一个按钮,当用户从RN界面调用原生代码就会进入到原生代码开发的界面中,而点击原生代码中的按钮就会返回到RN界面。

树自行车分割线

接上一节的代码。

1、在与MainApplication同级的目录下创建一个Activity。Activity是android系统最小的调度单位。

04.jpg

创建名称为MyActivity的空活动。它会帮助我们生成一个自动布局文件做布局的工作。(此时若遇到错误,可以选择build->clean)

05.jpg

2、command+enter点击进入activity_my中,此时会打开布局文件。将左下角的Design切换成Text文件。在该文件中,为原生界面创建一个按钮并且布局。

06.jpg

xmlns:android表示设置xmlns的命名空间,没有这句话就无法设置属性的约束。

在该界面上创建一个按钮,为按钮绑定一个方法onBack。

android:layout_width = "match_parent"

android:layout_height="match_parent"

xmlns:android = "http://schemas.android.com/apk/res/android"

>

android:text="goBack"

android:onClick="onBack"

android:layout_centerInParent="true"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

/>

3、回到新创建的MyActivity代码,实现onBack方法。

//点击按钮,直接完成

public void onBack(View v){

finish();

}

4、到MyNativeModule原生模块中去实现Activity

上文中已经说过,Activity是android系统的最小调度单位,而Intent则是安卓的进程之间、activity之间、线程之间交换数据的载体。

//方法不能返回值 因为被调用的原生代码是异步的 原生代码执行结束之后只能通过回调函数或者发送消息给RN

@ReactMethod

public void rnCallNative(String msg){

Toast.makeText(mContext,msg,Toast.LENGTH_LONG).show();

Intent intent = new Intent(mContext,MyActivity.class); //创建一个意图,意图是android进程之间、线程之间、交换数据的载体

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //一定要加上这句

mContext.startActivity(intent);

}

效果图如下:

07RN与原生切换.gif

三、RN用Promise机制与安卓原生代码通信

使用Promise机制也是RN与原生通信的一种方式。在原生代码的MyNativeModule文件中创建桥接方法。当桥接的原生方法的最后一个参数是一个Promise对象,那么该方法会返回一个JS的Promise对象给与之对应的js方法。

与上文类似,需要暴露给RN的方法不能有返回值,并且要以注释@ReactMethod标识。

@ReactMethod

public void rnCallNative_promise(String msg,Promise promise){

Toast.makeText(mContext,msg,Toast.LENGTH_SHORT).show();

//得到组件名称

String componentName = getCurrentActivity().getComponentName().toString();

promise.resolve(componentName);

}

原生代码已经实现。接下来要实现的就是RN的代码。在RN中创建一个方法,这个方法内部使用NativeModules组件来调用原生模块提供的名称,进而找到要调用的原生方法。原生方法最后一个参数是一个promise,所以在js中用.then的方法实现即可。

callAndroid_promise(){

NativeModules.ToastModule.rnCallNative_promise('promise调用原生').then(

(msg) => {

console.log('promise收到消息:'+msg);

}

).catch(

(err)=>{

console.log(err);

}

)

}

到渲染方法中,调用方法

Promise通信

给Text组件设置样式

welcome: {

fontSize: 16,

textAlign: 'left',

margin: 10

}

结果图如下:

08.jpg

用Debug进行调试,得到结果如下:

09.jpg

四、RN用callback回调方式与安卓原生代码通信

按照上文中提到的方式,在原生模块中暴露一个桥接方法给RN调用。

参数传入一个成功的回调和一个失败的回调。

@ReactMethod

public void measureLayout(Callback errorCallback,Callback successCallback){

try {

successCallback.invoke(100,100,200,200); //调用回调函数,返回结果

}catch (IllegalViewOperationException e){

errorCallback.invoke(e.getMessage());

}

}

在js中实现回调方法。同样是通过NativeModules组件寻找到桥接名称ToastModule,进而找到想要调用的方法。拿到返回的参数,做功能处理。

callAndroid_callback(){

NativeModules.ToastModule.measureLayout(

(msg)=>{

console.log(msg);

},

(x,y,width,height)=>{

console.log('x坐标:'+x+'y坐标:'+y+'高:'+height+'宽'+width);

}

)

}

10.jpg

在Debug调试下,点击callback通信文字,可以看到如下结果:

11.jpg

在使用回调函数时会呈现出某些缺点,比如说每次调用只应当调用一次,多次调用可能会出现意想不到的结果,并且用这种方法安卓原生代码是无法主动发送信息给RN侧的。而消息机制的方式就可以进行消息的互相传递。

小孩与狗童真分隔线

rn代码与android,RN与原生通讯(安卓篇)相关推荐

  1. Android 仿照QQ剪裁头像(完结篇)

    转载请注明出处: http://blog.csdn.net/u014163726?viewmode=contents 本文出自Wrh的博客 闲扯 最近刚好空闲下来又因为以前有人问到过这个仿qq上传头像 ...

  2. android rn动态技术,ReactNative入门之android与rn初始化参数的传递

    1.基本理念 RN APP本质上也是原生APP,只是在原生APP中加入了React Native视图的支持. 因此获取RN APP的启动参数的方法原生APP是一样的,获取启动参数后再通过合适的方法传递 ...

  3. 泛前端知识图谱(Web/iOS/Android/RN)

    泛前端知识图谱(Web/iOS/Android/RN) 从属于笔者的程序员成长道路上的阅读学习资料工具集锦系列,主要是对于笔者这几年在前端开发中总结出来的知识点的归集与整理,也是笔者的笔记排布目录结构 ...

  4. android rn 和webview,RN Webview与Web的通信与调试

    React Native Version:0.51 RN 在 0.37 版本中加入了WebView功能,所以想要在使用WebView,版本必须>=0.37,发送的 message 只能是字符串, ...

  5. android keyevent列表,Android KeyEvent KeyCode 原生安卓代码对照表

    Android KeyEvent KeyCode 原生安卓代码对照表: public static final int FLAG_WOKE_HERE = 1; public static final  ...

  6. android h5和原生方法调用,Android原生与H5通信

    如今,混合开发似乎成为了主流.H5拥有跨平台的优势,却存在性能上的问题正好可以用搭建原生壳承载H5代码的方式去解决. 如何理解这种方式,就好像说Android原生代码封装外壳,内部包含H5代码作为核心 ...

  7. Android嵌入Udesk即时通讯网页插件(一、入门)

    作者:张振琦 Android 系统上实现Udesk即时通讯,除了使用Udesk提供的原生sdk以外还可以嵌入Udesk提供的即时通讯网页插件.Udesk即时通讯网页插件的内容,大家可以参考<Ud ...

  8. (003)RN开发VSCode配置RN以及常用快捷键

    VS Code 开源 轻量级:更少的内存和 CPU 占用率 更大的社区:插件,教程等 使用 JavaScript 和 TypeScript 时更好一点 更多"面向未来" WebSt ...

  9. Android中进程间通讯 AIDL

    Android中进程间通讯 AIDL IDL Interface Description Language  接口描述语言 AIDL Android IDL 适用场景:    client进程必须是A ...

最新文章

  1. PDU (协议数据单元)
  2. MATLAB基本操作(二):数组中操作
  3. MySQL等值传播(low!就是一层窗户纸)
  4. 计算机主机主要构成,台式电脑主机的硬件组成部分简介
  5. H5|web移动前端自适应适配布局解决方案
  6. Python3 爬虫学习笔记 C18【爬虫框架 pyspider — 深入理解】
  7. 设计模式之——工厂模式
  8. pythonweb开发工作内容_我的第一个python web开发框架(5)——开发前准备工作(了解编码前需要知道的一些常识)...
  9. 演示FilterConfig接口的getInitParameter(String name)方法
  10. 基于centos的FasfDFS安装配置
  11. USACO / Mother's Milk (DFS)
  12. DOCKER基础技术:LINUX NAMESPACE(下)
  13. 基于QT的网络五子棋游戏程序的设计与实现
  14. java发送邮件-java工具类
  15. 【算法竞赛学习笔记】平衡树专题——替罪羊树
  16. 【02.06-02.13】长赢计划主理人“ETF拯救世界”微博精选
  17. C++ new关键字分析
  18. SPARC架构下的反汇编(一)——SPARC简介
  19. 使用java实现简单五子棋
  20. 为何64位的.NET程序不能申请超过2G的空间

热门文章

  1. MATLAB信号处理之信号的采样
  2. Python中的join函数
  3. 十几减9的口算题_小学一年级下册十几减9数学教案
  4. flinkCdc的mysql配置及java测试代码
  5. html树图制作,d3.js制作树结构图
  6. 比较两个对象中全部属性值是否相等
  7. Springboot — 用更优雅的方式发HTTP请求(RestTemplate详解)
  8. html的article标签,介绍一个html5做的网站,以及article标签的用法
  9. 2019-06-02 Java学习日记之多线程上
  10. Android Room 之存储 Objects 中的 List