Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >React native和原生之间的通信

React native和原生之间的通信

作者头像
xiangzhihong
发布于 2018-02-05 07:29:24
发布于 2018-02-05 07:29:24
5K0
举报
文章被收录于专栏:向治洪向治洪

RN中文网关于原生模块(Android)的介绍可以看到,RN前端与原生模块之

间通信,主要有三种方法:

1)使用回调函数Callback,它提供了一个函数来把返回值传回给JavaScript

2)使用Promise来实现。

3)原生模块向JavaScript发送事件。

关于使用回调,这是最简单的一种通信,这里可以看看官网的实现,今天要讲的是滴三种由原生模块向JavaScript发送事件。

(1)首先,你需要定义一个发送事件的方法。如下所示:

代码语言:js
AI代码解释
复制
/*原生模块可以在没有被调用的情况下往JavaScript发送事件通知。 
    最简单的办法就是通过RCTDeviceEventEmitter, 
    这可以通过ReactContext来获得对应的引用,像这样:*/ 
 public static void sendEvent(ReactContext reactContext, String eventName, @Nullable WritableMap paramss)  
    {  
        System.out.println("reactContext="+reactContext);  
 
        reactContext  
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)  
                .emit(eventName, paramss);  
 
    }  

其中方法名可以任意,但是参数不可改变。该方法可以放在你要复用的原生类中(即为原生类1)。

需要注意的是,由于版本问题,该函数中的参数reactContext有可能为null,此时会报NullPointException的错误。所以我们需要手动给reactContext赋值,见步骤2.

(2)我们在原生类1中,定义变量public static ReactContext  MyContext;

然后在我们自定义的继承至ReactContextBaseJavaModule的类中给reactContext赋值。

如下所示:

代码语言:java
AI代码解释
复制
public class MyModule extends ReactContextBaseJavaModule {  
 
 private BluetoothAdapter mBluetoothAdapter = null;  
 public MyModule(ReactApplicationContext reactContext) {  
 super(reactContext);  
 
        原生类1.MyContext=reactContext;  
 
 
    }  
.......以下写被@ReactNative所标注的方法  
............................  
...................  
}  

此时,reactContext将不会是null。也就不会报错。

(3)在某个原生函数中向JavaScript发送事件。如下所示:

代码语言:java
AI代码解释
复制
WritableMap event = Arguments.createMap();  
sendEvent(MyContext, "EventName",event);  

(4)在RN前端监听事件。首先导入DeviceEventEmitter,即import{ DeviceEventEmitter } from 'react-native'

然后使用componentWillMount建立监听。

代码如下:

代码语言:js
AI代码解释
复制
componentWillMount(){    
 
                    DeviceEventEmitter.addListener('EventName', function() {    
 
                         alert("send success");    
                       });   
 
 
}  

注意:该监听必须放在class里边,和render、const对齐。

下边展示一个完整Demo,Demo功能如下:

(1)JavaScript端在监听一个事件。

(2)点击前端某行文字,调用原生方法。

(3)在原生方法中,延迟3s后向前端发送对应事件。

(4)前端接收到事件后,给出alert提示。

代码如下:

ManiActivity.Java

代码语言:js
AI代码解释
复制
package com.ywq;  
 
import com.facebook.react.ReactActivity;  
 
public class MainActivity extends ReactActivity {  
 
 /** 
     * Returns the name of the main component registered from JavaScript. 
     * This is used to schedule rendering of the component. 
     */ 
 @Override 
 protected String getMainComponentName() {  
 return "ywq";  
    }  
}  

ManiApplication.java

代码语言:js
AI代码解释
复制
package com.ywq;  
 
import android.app.Application;  
import android.util.Log;  
 
import com.facebook.react.ReactApplication;  
import com.facebook.react.ReactInstanceManager;  
import com.facebook.react.ReactNativeHost;  
import com.facebook.react.ReactPackage;  
import com.facebook.react.shell.MainReactPackage;  
 
import java.util.Arrays;  
import java.util.List;  
 
public class MainApplication extends Application implements ReactApplication {  
 
 private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {  
 @Override 
 protected boolean getUseDeveloperSupport() {  
 return BuildConfig.DEBUG;  
    }  
 
 @Override 
 protected List<ReactPackage> getPackages() {  
 return Arrays.<ReactPackage>asList(  
 new MainReactPackage(),  
 new MyPackage()  
      );  
    }  
  };  
 
 @Override 
 public ReactNativeHost getReactNativeHost() {  
 return mReactNativeHost;  
  }  
}  

MyModule.java

代码语言:java
AI代码解释
复制
package com.ywq;  
 
import com.facebook.react.bridge.ReactApplicationContext;  
import com.facebook.react.bridge.ReactContextBaseJavaModule;  
import com.facebook.react.bridge.ReactMethod;  
 
/** 
 * Created by Administrator on 2016/10/30. 
 */ 
 
public class MyModule extends ReactContextBaseJavaModule {  
 
 public MyModule(ReactApplicationContext reactContext) {  
 
 super(reactContext);  
 
 //给上下文对象赋值 
        Test.myContext=reactContext;  
    }  
 
 @Override 
 public String getName() {  
 
 return "MyModule";  
    }  
 
 
 @ReactMethod 
 public void  NativeMethod()  
    {  
 //调用Test类中的原生方法。 
 new Test().fun();  
    }  
}  

MyPackage.java

代码语言:java
AI代码解释
复制
package com.ywq;  
 
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;  
 
/** 
 * Created by Administrator on 2016/10/30. 
 */ 
 
public class MyPackage implements ReactPackage {  
 @Override 
 public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {  
 
        List<NativeModule> modules=new ArrayList<>();  
        modules.add(new MyModule(reactContext));  
 
 return modules;  
    }  
 
 @Override 
 public List<Class<? extends JavaScriptModule>> createJSModules() {  
 return Collections.emptyList();  
    }  
 
 @Override 
 public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {  
 return Collections.emptyList();  
    }  
}  

Test.java

代码语言:java
AI代码解释
复制
package com.ywq;  
 
import android.provider.Settings;  
import android.support.annotation.Nullable;  
 
import com.facebook.react.bridge.Arguments;  
import com.facebook.react.bridge.ReactContext;  
import com.facebook.react.bridge.WritableMap;  
import com.facebook.react.modules.core.DeviceEventManagerModule;  
 
/** 
 * Created by Administrator on 2016/10/30. 
 */ 
 
public class Test {  
 
 //定义上下文对象 
 public static ReactContext myContext;  
 
 //定义发送事件的函数 
 public void sendEvent(ReactContext reactContext, String eventName, @Nullable WritableMap params)  
    {  
        System.out.println("reactContext="+reactContext);  
 
        reactContext  
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)  
                .emit(eventName,params);  
    }  
 
 public void fun()  
    {  
 //在该方法中开启线程,并且延迟3秒,然后向JavaScript端发送事件。 
 new Thread(new Runnable() {  
 @Override 
 public void run() {  
 
 try {  
                    Thread.sleep(3000);  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
 
 //发送事件,事件名为EventName 
                WritableMap et= Arguments.createMap();  
                sendEvent(myContext,"EventName",et);  
 
 
            }  
        }).start();  
 
    }  
 
 
}  

前端index.android.js代码如下:

代码语言:java
AI代码解释
复制
/** 
 * Sample React Native App 
 * https://github.com/facebook/react-native 
 * @flow 
 */ 
 
import React, { Component } from 'react';  
import {  
 AppRegistry,  
  StyleSheet,  
  Text,  
  DeviceEventEmitter,  
  NativeModules,  
  View  
} from 'react-native';  
 
export default class ywq extends Component {  
 
    componentWillMount(){    
 //监听事件名为EventName的事件 
                    DeviceEventEmitter.addListener('EventName', function() {    
 
 
 
                         alert("send success");    
 
                       });   
 
 
}  
 
  constructor(props) {  
 super(props);  
 this.state = {  
        content: '这个是预定的接受信息',  
    }  
}  
 
  render() {  
 return (  
      <View style={styles.container}>  
 
        <Text style={styles.welcome}  
         onPress={this.callNative.bind(this)}  
        >  
          当你点我的时候会调用原生方法,原生方法延迟3s后会向前端发送事件。  
          前端一直在监听该事件,如果收到,则给出alert提示!  
        </Text>  
 
        <Text style={styles.welcome} >  
        {this.state.content}  
         </Text>  
 
 
      </View>  
    );  
  }  
 
  callNative()  
  {  
    NativeModules.MyModule.NativeMethod();  
  }  
 
 }  
 
const styles = StyleSheet.create({  
  container: {  
    flex: 1,  
    justifyContent: 'center',  
    alignItems: 'center',  
    backgroundColor: '#F5FCFF',  
  },  
  welcome: {  
    fontSize: 20,  
    textAlign: 'center',  
    margin: 10,  
  },  
  instructions: {  
    textAlign: 'center',  
    color: '#333333',  
    marginBottom: 5,  
  },  
});  
 
AppRegistry.registerComponent('ywq', () => ywq);  

运行结果如下所示:

点击之前:

调用原生方法并且等待3s后:

再说一个值得注意的地方,一般我们在接收到原生模块主动发来的事件时,都会进行一些操作,如更新UI,而不仅仅是弹出alert 。

例如我们需要更新UI,代码如下:

代码语言:js
AI代码解释
复制
/** 
 * Sample React Native App 
 * https://github.com/facebook/react-native 
 * @flow 
 */ 
 
import React, { Component } from 'react';  
import {  
 AppRegistry,  
  StyleSheet,  
  Text,  
  DeviceEventEmitter,  
  NativeModules,  
  View  
} from 'react-native';  
 
export default class ywq extends Component {  
 
    componentWillMount(){    
 //监听事件名为EventName的事件 
                    DeviceEventEmitter.addListener('EventName', function() {    
 
 this.showState();  
 
                         alert("send success");    
 
                       });   
 
 
}  
 
  constructor(props) {  
 super(props);  
 this.state = {  
        content: '这个是预定的接受信息',  
    }  
}  
 
  render() {  
 return (  
      <View style={styles.container}>  
 
        <Text style={styles.welcome}  
         onPress={this.callNative.bind(this)}  
        >  
          当你点我的时候会调用原生方法,原生方法延迟3s后会向前端发送事件。  
          前端一直在监听该事件,如果收到,则给出alert提示!  
        </Text>  
 
        <Text style={styles.welcome} >  
        {this.state.content}  
         </Text>  
 
 
      </View>  
    );  
  }  
 
  callNative()  
  {  
    NativeModules.MyModule.NativeMethod();  
  }  
 
  showState()  
  {  
 this.setState({content:'已经收到了原生模块发送来的事件'})  
  }  
}  
 
const styles = StyleSheet.create({  
  container: {  
    flex: 1,  
    justifyContent: 'center',  
    alignItems: 'center',  
    backgroundColor: '#F5FCFF',  
  },  
  welcome: {  
    fontSize: 20,  
    textAlign: 'center',  
    margin: 10,  
  },  
  instructions: {  
    textAlign: 'center',  
    color: '#333333',  
    marginBottom: 5,  
  },  
});  
 
AppRegistry.registerComponent('ywq', () => ywq);  

很明显:当收到事件时,改变一个文本框的内容,即更新UI。

运行结果如下,说明在此function中不能使用this,也就是我们并不能更新UI。

那我们能做到在接收到事件后更新UI等后续操作吗?

使用胖箭头函数(Fat arrow functions)

修改UI代码如下:

代码语言:java
AI代码解释
复制
/** 
 * Sample React Native App 
 * https://github.com/facebook/react-native 
 * @flow 
 */ 
 
import React, { Component } from 'react';  
import {  
 AppRegistry,  
  StyleSheet,  
  Text,  
  DeviceEventEmitter,  
  NativeModules,  
  View  
} from 'react-native';  
 
export default class ywq extends Component {  
 
    componentWillMount(){    
 //监听事件名为EventName的事件 
 
                    DeviceEventEmitter.addListener('EventName', ()=> {    
 
 this.showState();  
                         alert("send success");    
 
                       });   
 
}  
 
  constructor(props) {  
 super(props);  
 this.state = {  
        content: '这个是预定的接受信息',  
    }  
}  
 
  render() {  
 return (  
      <View style={styles.container}>  
 
        <Text style={styles.welcome}  
         onPress={this.callNative.bind(this)}  
        >  
          当你点我的时候会调用原生方法,原生方法延迟3s后会向前端发送事件。  
          前端一直在监听该事件,如果收到,则给出alert提示!  
        </Text>  
 
        <Text style={styles.welcome} >  
        {this.state.content}  
         </Text>  
 
 
      </View>  
    );  
  }  
 
  callNative()  
  {  
    NativeModules.MyModule.NativeMethod();  
  }  
 
  showState()  
  {  
 this.setState({content:'已经收到了原生模块发送来的事件'})  
  }  
}  
 
const styles = StyleSheet.create({  
  container: {  
    flex: 1,  
    justifyContent: 'center',  
    alignItems: 'center',  
    backgroundColor: '#F5FCFF',  
  },  
  welcome: {  
    fontSize: 20,  
    textAlign: 'center',  
    margin: 10,  
  },  
  instructions: {  
    textAlign: 'center',  
    color: '#333333',  
    marginBottom: 5,  
  },  
});  
 
AppRegistry.registerComponent('ywq', () => ywq);  

运行之后,界面刷新了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-11-27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
React Native与Android 原生通信
我们用React Native 做混合开发的时候免不了要原生和React Native 进行通信交互,这篇文章就是分享原生模块与JS传递数据的几种方式。
HelloJack
2018/08/28
2.6K0
React Native调用原生组件
在React Native开发过程中,有时候我们可能需要访问平台的API,但react Native还没有相应的实现,或者是React Native还不支持一些原生的属性,我们需要调用原生代码来实现,或者是我们需要复用一些原来的Java代码,这个时候我们就需要创建一个原生模块来自己实现对我们需要功能的封装。 相关文档可以参照官方的介绍。 #实例 下面我们就通过实现一个自定义模块,来熟悉编写原生模块需要用的一些知识。该模块主要实现调用一些Android原生的功能,比如弹Toast,启动Activity等。
xiangzhihong
2018/01/26
1.8K0
ReactNative调用Android原生模块
有时候App需要访问平台API,但React Native可能还没有相应的模块包装;或者你需要复用一些Java代码,而不是用Javascript重新实现一遍;又或者你需要实现某些高性能的、多线程的代码,譬如图片处理、数据库、或者各种高级扩展等等。 我们把React Native设计为可以在其基础上编写真正的原生代码,并且可以访问平台所有的能力。要想实现访问Android原生API,总结一下,主要有以下几个步骤: 1. 创建一个原生模块 这个原生模块是一个继承ReactContextBaseJavaMod
xiangzhihong
2018/02/06
1.5K0
使用Leancloud实现React Native App的消息推送(Push Notification)- Android篇
在上一篇文章 中我们详细讲解了用Leancloud实现iOS消息推送的流程,今天本文将继续讲解实现Android的消息推送。
MudOnTire
2019/05/26
3.4K0
React Native使用原生组件
概述 有时候App需要访问平台API,但React Native可能还没有相应的模块包装;或者你需要复用一些Java代码,而不是用Javascript重新实现一遍;又或者你需要实现某些高性能的、多线程的代码,譬如图片处理、数据库、或者各种高级扩展等等。 我们知道React Native本身对这种偏业务和底层调用是不关心的,这时候我们就想到了原生组件,我们通过调用原生组件,然后经过特定的封装来达到效果。如我们在原生开发中常见的Toast为例: 原生模块封装 假设我们希望可以从Javascript发起一个T
xiangzhihong
2018/02/05
2.4K0
react-native 打开设置界面
iOS iOS打开设置还是比较简单的,使用Linking组件即可: Linking.openURL('app-settings:') .catch(err => console.log('error', err)) Android 1、在android/app/src/main/java/com/<projectname>/文件夹下创建opensettings文件夹 2、在这个文件夹下创建模块文件OpenSettingsModule.java(模块功能)和包文件OpenSettingsPackage.
mcq
2018/06/27
2K0
React Native调用原生UI组件
在React Native 中,其已经将几个常用的原生组件进行了封装,但是并不是所有系统的原始组件都被封装了,因此有时候我们不得不自己动手封装一下,从而能够使用那些React Native没有为我们封装的原生组件。为了方便讲解,我们选择第一个第三方库kenburnsview来讲解,kenburnsview是一个可以让图片在在页面移动或者放大缩小的库。 Android原生组件封装 1,继承SimpleViewManager,返回UI组件实例 首先,需要继承 SimpleViewManager 这个泛型类,
xiangzhihong
2018/02/06
1.7K0
Android与RN层的交互
Android跳转到RN页面 由于主客是以插件化的方式集成功能插件的,所以在主客中Android跳转到RN页面需要plugin、module和component。plugin、module不过多解释,component对应的是具体的js页面,要成功启动此页面,需要在对应的RN二方库中注册此页面。例如:
xiangzhihong
2022/11/30
6080
RN集成到Android原生项目实践
1.新建普通Android项目 新建一个普通的Android项目即可,打开Android Studio -> File -> New -> New Project… 按步骤执行即可。
用户1269200
2018/12/06
2.9K0
React Native Android原生模块开发实战|教程|心得
尊重版权,未经授权不得转载 本文出自:贾鹏辉的技术博客(http://www.devio.org) 告诉大家一个好消息,为大家精心准备的React Native视频教程发布了,大家现可以看视频学React Native了。 前言 一直想写一下我在React Native原生模块封装方面的一些经验和心得,来分享给大家,但实在抽不开身,今天看了一下日历发现马上就春节了,所以就赶在春节之前将这篇博文写好并发布(其实是两篇:要看iOS篇的点这里《React Native iOS原生模块开发》)。 我平
CrazyCodeBoy
2018/05/07
2.2K0
React Native Android原生模块开发实战|教程|心得
RN与原生通讯(安卓篇)一、RN调用安卓代码(简单)二、RN用消息机制方式与安卓原生代码切换三、RN用Promise机制与安卓原生代码通信四、RN用callback回调方式与安卓原生代码通信
明天和意外你永远都不知道哪一个先来,编程界亦是如此。例如某个已经有原生代码开发模块的项目要求用RN扩张某些功能;又例如,RN中未封装到的组件非得求助于原生代码。所以RN与原生代码通讯对于混合编程是至关
谦谦君子修罗刀
2018/05/02
4.1K0
RN与原生通讯(安卓篇)一、RN调用安卓代码(简单)二、RN用消息机制方式与安卓原生代码切换三、RN用Promise机制与安卓原生代码通信四、RN用callback回调方式与安卓原生代码通信
React Native运行原理解析
Facebook 于2015年9月15日推出react native for Android 版本, 加上2014年底已经开源的IOS版本,至此RN (react-native)真正成为跨平台的客户端框架。本篇主要是从分析代码入手,探讨一下RN在安卓平台上是如何构建一套JS的运行框架。 一、 整体架构 RN 这套框架让 JS开发者可以大部分使用JS代码就可以构建一个跨平台APP。 Facebook官方说法是learn once, run everywhere, 即在Android 、 IOS、 Browse
xiangzhihong
2018/02/05
6.3K0
React Native运行原理解析
React Native JSBundle拆包之原理篇
RN作为一款非常优秀的移动端跨平台开发框架,在近几年得到众多开发者的认可。纵观现在接入RN的大厂,如qq音乐、菜鸟、去哪儿,无疑不是将RN作为重点技术栈进行研发。
xiangzhihong
2022/11/30
3.3K0
React Native调用Android相机图库
概述 在很多的React Native开发中,我们需要调用原生的api实现调用相机和图库的功能,网上用的最多的开源库如:react-native-image-picker。关于react-native-image-picker的用法大家请看相关的文档。我们今天手动实现一份。 调用Android图库相机 创建项目 执行命令 : react-native init HeadImage 创建一个名为HeadImage的工程,可以使用命令先运行下Demo项目。 然后照一张图片,放到放到工程的 HeadImage\A
xiangzhihong
2018/01/26
1.8K0
iOS React Native 混合开发集成React Native
   有时候我们并不是需要全部使用React Native,我们想和原生混合开发,那我们应该怎么办呢。
星宇大前端
2019/01/15
2.3K0
react native 调用原生UI组件
在React Native开发过程中,有时我们想要使用原生的一个UI组件或者是js比较难以实现的功能时,我们可以在react Naitve应用程序中封装和植入已有的原生组件。 本文我们实现一个VideoView的本地调用。 React Native并没有给我们提供VideoView这个组件,那我们要播放视频的话,有两种方法:一种是借助WebView,一种就是使用原生的播放器。 Java端实现 新建VideoViewManager类,并继承SimpleViewManager,SimpleViewManag
xiangzhihong
2018/02/06
7.5K1
react native 调用原生UI组件
React Native移植原生Android
(一)前言 之前已经写过了有关React Native移植原生Android项目的文章,不过因为RN版本更新的原因吧,跟着以前的文章可能会出现一些问题,对于初学者来讲还是会有很多疑难的困惑的,而且官方的文档移植没有更新,最新版本集成方法已经发生很大变化啦~OK,今天我们用新版本进行走一遍流程,具体原来就不讲了,直接看移植步骤。 (二)前提准备工作 ①.首先我们有一个采用Gradle构建的Android应用项目,这个大家直接采用Android Studio进行创建一个项目即可。我这边新建一个目录TestInt
xiangzhihong
2018/02/05
1.8K0
React Native移植原生Android
ReactNative For Android 框架启动核心路径剖析
QQ空间开发团队
2016/10/13
5.7K0
ReactNative For Android 框架启动核心路径剖析
react-native绑定优酷SDK-附效果图和源码
ReactNative绑定优酷SDK需要用到两部分知识: 优酷本身的sdk绑定; RN与原生界面的交互; 效果: RN版本:0.49.3 代码更新日期:2017.10.26 下文也根据绑定需要分为两部
磊哥
2018/05/08
9840
react-native绑定优酷SDK-附效果图和源码
【Hybrid开发高级系列】ReactNative(三)——RN能力简介
http://facebook.github.io/react-native/docs/getting-started.html
江中散人_Jun
2023/10/16
4580
【Hybrid开发高级系列】ReactNative(三)——RN能力简介
推荐阅读
相关推荐
React Native与Android 原生通信
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档