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日

相关文章

  • Maven搭建springboot项目的方法步骤

    下面我将详细讲解如何使用Maven搭建Spring Boot项目的方法步骤。 1. 准备工作 在使用Maven进行项目构建前,首先需要在本地安装和配置Maven环境。可以根据官方文档进行下载和安装,也可以使用包管理工具进行安装,例如使用APT工具: sudo apt-get install maven 2. 创建Spring Boot项目 2.1 使用Spr…

    Java 2023年5月15日
    00
  • SpringBoot 之启动流程详解

    SpringBoot 之启动流程详解 概述 Spring Boot 是一个基于 Spring 框架的快速开发框架。它通过自动配置(auto-configuration)、约定大于配置(convention over configuration)等方式,大大简化了 Spring 应用的开发,使得开发者能更专注于业务逻辑开发。本文将详细介绍 Spring Boo…

    Java 2023年5月15日
    00
  • 解决MyEclipse中Maven设置jdk版本jdk1.8报错问题

    第一步:查看Maven仓库 首先,在MyEclipse中点击菜单栏中的“Window”选项,再依次点击“Show View” -> “Other”,在窗口中选择“Maven” -> “Maven Repositories”,即可打开Maven仓库视图。 第二步:定位jdk1.8版本的安装路径 在Maven仓库视图中,找到”Global Repos…

    Java 2023年5月20日
    00
  • struts升级到2.5.2遇到的问题及解决方案(推荐)

    Struts升级到2.5.2遇到的问题及解决方案 问题描述 在将Struts框架从版本1升级到版本2.5.2时,会遇到一些问题。其中最常见的问题是: 升级后项目无法启动。 在页面中使用标签库时,会出现错误或警告。 在使用一些功能(如文件上传、表单验证等)时,会出现错误或异常。 解决方案 为了解决这些问题,我们可以采取以下措施: 1. 更新web.xml文件 …

    Java 2023年5月20日
    00
  • java设计模式-组合模式详解

    Java设计模式-组合模式详解 什么是组合模式? 组合模式属于结构型设计模式,它将对象组合成树形结构,以表示’部分-整体’的层次关系。组合模式使得用户对单个对象和组合对象的使用具有一致性,通常适用于处理树形结构,或者希望将单个对象和组合对象以相同的方式进行处理。 组合模式主要包含以下两种角色: Component(抽象构件):定义了叶子和容器构件的公用接口,…

    Java 2023年5月26日
    00
  • Java OpenSSL生成的RSA公私钥进行数据加解密详细介绍

    针对“Java OpenSSL生成的RSA公私钥进行数据加解密详细介绍”的话题,以下是完整攻略的介绍: 一、概述 OpenSSL是一个开源的安全套接字层(SSL)实现库,能够实现多种安全协议,包括SSL和TLS。Java OpenSSL是使用Java编写的,利用OpenSSL库生成RSA公私钥,以及使用公私钥进行数据的加解密。 本文将详细介绍Java Ope…

    Java 2023年5月19日
    00
  • JSP分页显示的实例代码

    JSP分页显示的实例代码需要以下步骤: 1. 准备数据 首先,我们需要准备一些数据,以便在JSP页面中分页显示。可以从数据库中查询相关数据,或者手动设置一些数据。 int pageSize = 5; //每页显示5条数据 int currentPage = 1; //当前页码 List<String> dataList = new ArrayLi…

    Java 2023年6月15日
    00
  • Spring MVC实现一次简单的CRUD示例

    下面我来详细讲解一下“Spring MVC实现一次简单的CRUD示例”的完整攻略。 什么是Spring MVC? Spring MVC是Spring Framework的一部分,它是一种基于Java的Web框架,用于开发企业级Web应用程序。Spring MVC使用模型-视图-控制器(MVC)模式进行设计和实现。 Spring MVC实现CRUD CRUD是…

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