React Native JSI实现RN与原生通信的示例代码

React Native JSI 是 React Native 的一个新特性,它可以实现 RN 与原生端的通信。JSI 基于 C++,所以可以很好地利用移动设备的 CPU 和 GPU 功能,从而提高应用程序的性能和可维护性。

要使用 RN JSI,需要在项目中安装相应的模块和库,例如 Folly 和 TurboModules。接下来,我们将详细讲解如何在 React Native 中实现 JSI 与原生通信的示例代码。

步骤 1:安装依赖模块

在 React Native 项目中,使用 npm 安装 Folly 和 TurboModules 模块:

npm install folly
npm install react-native-turbomodules

步骤 2:创建原生模块

接下来需要创建原生模块,并将其链接到 React Native 应用程序中。我们可以使用 C 语言编写原生模块,因为 JSI 是基于 C++ 的。以下是一个用 C 语言编写的示例原生模块:

#include <jsi/jsi.h>

static jsi::Value toUpperCase(const jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *arguments, size_t count) {
  if (count != 1) {
    throw jsi::JSError(rt, "Expected one argument");
  }
  if (!arguments[0].isString()) {
    throw jsi::JSError(rt, "Expected a string argument");
  }
  std::string input = arguments[0].asString(rt).utf8(rt);
  std::transform(input.begin(), input.end(), input.begin(), ::toupper);
  return jsi::String::createFromUtf8(rt, input);
}

extern "C" {

  jsi::HostObjectBinding toUpperCaseBinding([](jsi::Runtime &rt) {
    jsi::Object exports(rt);
    exports.setProperty(rt, "toUpperCase", jsi::Function::createFromHostFunction(rt, jsi::PropNameID::forAscii(rt, "toUpperCase"), 1, toUpperCase));
    return exports;
  });

  __attribute__((visibility("default"))) jsi::HostObjectBinding *rn_test_toUpperCase_binding_entry() {
    return &toUpperCaseBinding;
  }

}

以上代码实现了一个名为 toUpperCase 的函数,用于将输入字符串转换为大写形式。这些功能将通过 JSI 转换并从 React Native JavaScript 代码中调用。

步骤 3:创建 JS 代码

接下来,我们将创建 JS 代码,并调用原生模块来转换字符串。以下是一个简单的 React Native JS 代码示例:

import { TurboModuleRegistry } from 'react-native';

const { toUpperCase } = TurboModuleRegistry.get('toUpperCase');

console.log(toUpperCase('hello world'));  // 输出 HELLO WORLD

以上代码通过 TurboModuleRegistry API 获取到 toUpperCase 函数,并使用它将字符串转换为大写形式。现在,您可以在原生代码中使用 toUpperCase ,并在 React Native JavaScript 中调用它了。

示例 1:使用原生模块重新实现 React Native 原生组件

以下是一个基本示例,演示如何使用原生模块重新实现 React Native 的原生组件:

#include <react/renderer/components/view/ViewShadowNode.h>

namespace facebook {
namespace react {

class ViewShadowNodeWithSize: public ViewShadowNode {
public:
  ViewShadowNodeWithSize() = default;
  void layout(LayoutContext layoutContext) override {
    StyleLayoutNode::layout(layoutContext);

    auto layoutMetrics = getLayoutMetrics();
    layoutMetrics.frame.size.width = 200;
    layoutMetrics.frame.size.height = 100;

    setLayoutMetrics(layoutMetrics, layoutContext.getLayoutConstraints());
  }

  static ShadowNode *createTag() {
    return new ViewShadowNodeWithSize();
  }
};

} // namespace react
} // namespace facebook

extern "C" {

std::shared_ptr<facebook::react::ViewShadowNodeWithSize> rn_test_createautoslizeshadownode() {
  return std::make_shared<facebook::react::ViewShadowNodeWithSize>();
}

}

上面的代码是一个可调整大小的 ShadowNode 的增强版本,其大小能够是 200 x 100,这是我们在 layout() 方法中硬编码的。接下来,我们需要编写 JavaScript 代码,来使用该模块创建您的自定义 ShadowNode 的示例:

import { requireNativeComponent } from 'react-native';

const AutoSizedView = requireNativeComponent('AutoSizedView', null);

function App() {
  return (
    <AutoSizedView style={{flex: 1, backgroundColor: 'blue'}} />
  );
}

示例 2:使用原生模块扩展 React Native 功能

以下是一个扩展 RN Navigation 组件的示例,演示如何在原生 C++ 中实现一个更好的导航栏组件:

#include <react/renderer/components/navigation/NavigationShadowNode.h>
#include <react/renderer/components/navigation/NavigationBarShadowNode.h>

#include <react/renderer/components/view/ViewEventEmitter.h>
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/components/view/ViewShadowNode.h>
#include <react/renderer/core/LayoutMetrics.h>

namespace facebook {
namespace react {

class BetterNavbarShadowNode: public NavigationBarShadowNode {
  using Super = NavigationBarShadowNode;

public:
  BetterNavbarShadowNode() = default;
  void layout(LayoutContext layoutContext) override {
    auto layoutMetrics = getLayoutMetrics();
    layoutMetrics.frame.size.height = 75;
    setLayoutMetrics(layoutMetrics, layoutContext.getLayoutConstraints());

    Super::layout(layoutContext);
  }

  void didUpdateProps() override {
    Super::didUpdateProps();

    auto prop = traitValue("foo");
    if (prop && prop->isNumber()) {
      auto eventEmitter = getViewShadowNode()->getEventEmitter();
      eventEmitter->dispatchEvent("fooChange", folly::dynamic::object("foo", prop->getNumber()));
    }
  }

  static ShadowNode *createTag() {
    return new BetterNavbarShadowNode();
  }
};

class BetterNavigationShadowNode: public NavigationShadowNode {
  using Super = NavigationShadowNode;

public:
  BetterNavigationShadowNode() = default;
  static ShadowNode *createTag() {
    return new BetterNavigationShadowNode();
  }
};

} // namespace react
} // namespace facebook

extern "C" {

std::shared_ptr<facebook::react::NavigationShadowNode> rn_test_createBetterNavigation() {
  return std::make_shared<facebook::react::BetterNavigationShadowNode>();
}

std::shared_ptr<facebook::react::NavigationBarShadowNode> rn_test_createBetterNavbar() {
  return std::make_shared<facebook::react::BetterNavbarShadowNode>();
}

}

上述 C++ 代码是一个改进 React Native Navigation Bar 组件的实现,我们在这里增加了一个名称为 foo 的 trait ,当它的数值被更新时,它将触发自定义事件 fooChange。现在,我们需要编写 JavaScript 代码来使用该模块:

import { requireNativeComponent } from 'react-native';

const BetterNavbar = requireNativeComponent('BetterNavbar', null);

function App() {
  return (
    <BetterNavbar style={{ height: 75 }} foo={42} onFooChange={value => console.log(`foo is now ${value}`)} />
  );
}

结论

React Native JSI 的功能强大且高效,可以帮助编写更加高效、高性能和可维护的 React Native 应用程序。我们的文本提供了使用 RN JSI 实现与原生通信的示例代码的完整攻略,以及两个示例的详细说明,希望能对您有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:React Native JSI实现RN与原生通信的示例代码 - Python技术站

(0)
上一篇 2023年6月15日
下一篇 2023年6月15日

相关文章

  • Java中获取子字符串的几种方法示例

    关于Java中获取子字符串的几种方法,其实有很多种,下面我来逐一讲解。 String类的substring方法 String类的substring方法可以用于截取字符串中的一部分,包含起始位置但不包含结尾位置。方法的签名如下: public String substring(int beginIndex, int endIndex) 其中,beginInde…

    Java 2023年5月27日
    00
  • 使用sts工具、SpringBoot整合mybatis的详细步骤

    下面是详细步骤: 准备环境 JDK8+ Maven3.0+ SpringBoot2.0+ STS(Spring Tool Suite)/ IntelliJ IDEA 创建SpringBoot项目 使用STS或者IntelliJ IDEA创建一个新的SpringBoot项目,选择Web依赖,根据个人喜好选择模板。 在pom.xml中添加MyBatis依赖: x…

    Java 2023年5月20日
    00
  • 修改Tomcat运行时jvm编码问题

    下面是修改Tomcat运行时jvm编码问题的完整攻略: 1. 了解Tomcat jvm编码问题 Tomcat是一个开源的Web应用服务器,使用Java语言编写,可以运行Java Web应用程序。在使用Tomcat时,我们有时会遇到在Tomcat运行时出现乱码的问题,这是由于Tomcat运行时jvm编码设置不正确所导致的。 jvm是Java Virtual M…

    Java 2023年5月20日
    00
  • MyBatis几种不同类型传参的方式总结

    Sure! MyBatis几种不同类型传参的方式总结 在MyBatis中,传参是非常重要的一部分。正确的传递参数对于正确的执行SQL语句非常关键。本文将介绍MyBatis的不同传参方式及其使用示例。 1. 基本参数类型 基本参数类型指的是Java中的简单数据类型,如int、String、float等,也包括其相应的包装类型。在Mapper文件中,可以直接使用…

    Java 2023年5月20日
    00
  • 理解JPA注解@GeneratedValue的使用方法

    JPA(Java Persistence API)是Java EE中关于对象持久化的标准接口,它将对象映射成数据库中的表,使得Java开发者可以直接使用面向对象的思想来操作数据库。其中@GeneratedValue注解是JPA中常用的注解之一。本文将为你详细介绍@GeneratedValue注解的使用方法及注意点。 什么是@GeneratedValue注解?…

    Java 2023年5月20日
    00
  • Java日期时间类及计算详解

    Java日期时间类及计算详解 Java中提供了多个日期时间类,用于操作和计算日期和时间。本文将详细介绍Java日期时间类及计算的相关知识。 Date类 Date类是Java中最基本的日期时间类。它表示时间戳,即自1970年1月1日00:00:00至当前日期时间所经过的毫秒数。 获取当前日期时间 要获取当前日期时间,可以使用Date类的无参构造函数和toStr…

    Java 2023年5月20日
    00
  • PostgreSql JDBC事务操作方法详解

    PostgreSql JDBC事务操作方法详解 在Java应用程序中,使用JDBC访问PostgreSQL数据库时,我们经常需要使用事务来保证数据的一致性和可靠性。本文将详细介绍使用PostgreSQL JDBC驱动程序执行事务的方法。 驱动程序获取 我们需要先通过以下方式获取PostgreSQL JDBC驱动程序,然后将其放在Java应用程序中: Mave…

    Java 2023年6月16日
    00
  • 如何理解Java类装载机制?

    如何理解Java类装载机制 Java类装载机制是Java虚拟机实现面向对象的重要机制之一。在Java中,只有通过类装载机制才能把类的二进制文件加载到内存中。 类加载机制的概念 Java类装载机制指的是Java将类的字节码从硬盘加载到内存中,并进行解析的过程。在Java程序运行期间,类可能会被多次加载、卸载,或者出现别名等情况,这都是由类装载机制所控制的。 类…

    Java 2023年5月11日
    00
合作推广
合作推广
分享本页
返回顶部