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

yizhihongxing

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日

相关文章

  • SpringBoot中的五种对静态资源的映射规则的实现

    SpringBoot中的五种对静态资源的映射规则的实现 在SpringBoot中,我们可以使用五种不同的方式来映射静态资源,包括: 默认的映射规则 自定义的映射规则 使用WebMvcConfigurerAdapter来配置映射规则 使用@Configuration注解来配置映射规则 使用@EnableWebMvc注解来配置映射规则 下面将详细介绍这五种映射规…

    Java 2023年5月18日
    00
  • python实现提取jira bug列表的方法示例

    下面我将详细讲解Python实现提取Jira bug列表的方法示例的完整攻略。 1. 准备工作 在使用Python获取Jira bug列表前,我们需要先为访问Jira做好准备工作。具体做法是: 在Jira中创建一个新的用户,用于Python访问Jira时使用。 在Jira中为该用户授权,最好只授权访问相关的项目和数据,以保证安全性。 在Python中安装相关…

    Java 2023年6月16日
    00
  • java Scanner输入数字、字符串过程解析

    接下来我将为您提供关于Java中Scanner输入数字、字符串的详细描述。 Scanner类 Java中的Scanner类提供了一种可以解析基本数据类型和字符串的简便方法。Scanner可以从文件、输入流、文本字符串和其他源读取格式化的输入内容。我们可以使用Scanner进行数字和字符串输入处理。 以下是Scanner类的构造方法: Scanner(Inpu…

    Java 2023年5月27日
    00
  • Java面试经验+最新BAT面试资料分享给大家(小结)

    Java面试经验+最新BAT面试资料分享给大家(小结) 这篇文章将帮助大家准备BAT公司的Java面试,希望对大家有所帮助。 程序员面试的模式 程序员面试一般分为以下几轮: 简历筛选 笔试 技术面试 综合素质面试 HR面试 针对每一轮面试,我们都需要做好充足的准备。 简历筛选 在简历筛选阶段,我们需要注意以下几个点: 简历的格式需要清晰简洁,突出重点 突出自…

    Java 2023年5月20日
    00
  • IDEA安装阿里巴巴编码规范插件的两种方式详解(在线安装和离线安装)

    下面是详细的攻略过程: 一、在线安装方式 打开IntelliJ IDEA编辑器,点击菜单栏中的「File」,选择下拉菜单中的「Settings」。 在弹出的设置页面中,找到「Plugins」选项,点击左侧的「Marketplace」,在搜索框输入「Alibaba」,点击搜索图标。 在搜索结果中会出现「Alibaba Java Coding Guideline…

    Java 2023年5月20日
    00
  • SpringBoot利用AOP实现一个日志管理详解

    来讲一下SpringBoot利用AOP实现一个日志管理的详细攻略。 一、前置知识 在讲解具体实现之前,需要对一些前置知识进行解释: 1.1 AOP AOP(Aspect Oriented Programming,面向切面编程)是一种编程思想,可以将与业务无关的部分(例如日志记录、权限验证等)剥离出来,通过以独立的方式进行定义和维护,将其在需要时运用进程序设计…

    Java 2023年5月19日
    00
  • 教你如何使用JAVA POI

    教你如何使用JAVA POI 什么是JAVA POI JAVA POI是Apache Software Foundation开发的一组开源API,用于操作各种Microsoft Office格式的文档,例如Excel、Word、PowerPoint等。在JAVA程序中使用JAVA POI可以方便地读取、创建和修改这些文档。 安装JAVA POI 要在JAVA…

    Java 2023年5月26日
    00
  • idea下载svn的项目并且运行操作

    下面是详细讲解“idea下载svn的项目并且运行操作”的完整攻略: 步骤一:安装SVN插件 首先,要在IntelliJ IDEA中安装SVN插件。打开IntelliJ IDEA,然后点击“File”菜单,在下拉列表中选择“Settings”选项。在弹出的窗口中,选择“Plugins”选项卡,搜索“Subversion Integration”插件,安装并启用…

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