Получите ранний доступ к TurboModules и Codegen в React Native.
При использовании React Native ранее мы взаимодействовали между «родным» слоем нашего приложения и слоем «JavaScript» с помощью моста JavaScript. Хотя мост выполнял свою задачу, у него было несколько серьезных проблем.
Во-первых, мост был асинхронным, то есть он объединял несколько вызовов на собственный уровень и вызывал их с заданным интервалом. Если этого было недостаточно, на нативной стороне вам приходилось сериализовать и десериализовать данные, поступающие в мост и из моста. Эти две операции вместе сделали работу довольно медленной.
Во-вторых, мост не был типобезопасным. Вы в значительной степени передавали по мосту все, что хотели, и нативный уровень должен был что-то делать для обработки этих данных. Наконец, при запуске приложения все нативные модули должны быть загружены в память. Это означало медленное время запуска для пользователей.
Создатели React Native представили Codegen и TurboModules для решения этих проблем. TurboModules решают проблемы с асинхронностью и загрузкой, потому что они ведут себя синхронно в JavaScript и откладывают загрузку в память, что позволяет приложению запускаться быстрее.
Codegen решает проблему безопасности типов, поскольку позволяет нам создавать интерфейсы, которые мы можем использовать, чтобы убедиться, что наш собственный код остается синхронизированным с данными, которые мы передаем из уровня JavaScript.
Это руководство покажет вам, как использовать Codegen и TurboModules вместе с React Native в Android. Вторая статья из этой серии будет посвящена тому же самому в iOS. Обратите внимание, что это руководство для первых пользователей, предназначенное для React Native с 0.68.2 по 0.69.0. Новая архитектура React Native все еще находится в процессе разработки и со временем может меняться. Если вы застряли, не стесняйтесь взглянуть на мой пример проекта здесь. Если вас заинтересовал мой видео-урок на эту тему, посмотрите мое видео здесь.
РЕДАКТИРОВАТЬ: пользователи React-Native 0.69.0 увидят ложные ошибки в Android Studio о том, что импорт не может быть найден. Я жаловался на эту проблему здесь, и Мета, кажется, знает об этом. Если вы будете следовать этим инструкциям и при необходимости импортировать из моего примера проекта, приложение все равно скомпилируется. Ошибки Android Studio возникают из-за ошибки в их IDE, а не в этом коде. Возможно, имеет смысл выполнить это руководство в коде Visual Studio, чтобы избежать шума ошибок Android Studio.
Что мы строим?
В этой статье мы собираемся создать простое приложение, которое вызывает TurboModule и печатает сообщение. Просто, я знаю, но с Codegen вы можете создавать функции настолько сложными, насколько вам нравится, после прочтения этого блога. Это будет выглядеть так:
Нативная установка React
Начните с создания проекта TypeScript с помощью следующей команды:
npx react-native init TurboModuleSampleProject --template react-native-template-typescript
Важно, чтобы мы использовали TypeScript, потому что Codegen требует, чтобы мы использовали типы. Ванильный JS-проект здесь не годится.
Далее давайте создадим папку с именем js
в корне проекта. Внутри js
мы собираемся создать файл с именем NativeSampleModule.ts
. Будьте очень осторожны, всегда добавляйте префикс имени вашего файла и модуля со словом Native. Если вы этого не сделаете, Codegen не сможет найти ваш код и ничего не сгенерирует. Это не дает вам никаких ошибок здесь и молча терпит неудачу. В завершение скопируйте и вставьте этот код в свой файл.
import type {TurboModule} from 'react-native'; import {TurboModuleRegistry} from 'react-native'; export interface Spec extends TurboModule { getHelloWorld(first: string, second: string): string; } export default TurboModuleRegistry.getEnforcing<Spec>('NativeSampleModule');
Настройка Android Gradle
В Android мы начинаем с перехода на уровень приложения build.gradle
и добавления этой строки в начало файла.
apply plugin: "com.facebook.react"
После этого нам нужно сообщить Android, где находится наш файл Codegen. Мы делаем это, добавляя этот код в строку 88
react { jsRootDir = rootProject.file("../js/") }
Затем найдите свойство enableHermes
и установите для него значение true
. Новая архитектура для React-Native не будет работать, если вы не используете Hermes. После этого раскомментируйте строку:
preBuild.dependsOn("generateCodegenArtifactsFromSchema")
Наконец, перейдите к gradle.properties
и установите newArchEnabled=true
Запускаем yarn android
для генерации нужных нам файлов
Написание нашего Java-кода
Теперь, когда мы настроили нашу сборку и сгенерировали привязки для функций JavaScript, давайте откроем папку android
в Android Studio и напишем собственный код.
Начните с поиска пакета com.turbomodulessampleproject
В этом пакете создайте новый файл с именем NativeSampleModuleImpl.java
. Внутри этого файла мы собираемся расширить интерфейс, созданный Codegen. Это будет выглядеть так.
package com.turbomodulesampleproject; import androidx.annotation.NonNull; import com.facebook.fbreact.specs.NativeSampleModuleSpec; import com.facebook.react.bridge.ReactApplicationContext; public class NativeSampleModuleImpl extends NativeSampleModuleSpec { public static String NAME = "NativeSampleModule"; public NativeSampleModuleImpl(ReactApplicationContext reactContext) { super(reactContext); } @Override public String getHelloWorld(String first, String second) { return "HelloWorld: " + first + " " + second; } @NonNull @Override public String getName() { return NAME; } }
Далее мы хотим добавить наш пакет на хост приложения. Для этого найдите каталог newarchitecture
под пакетом турбо-модулей сверху и найдите файл MainApplicationReactNativeHost.java
. Переопределите метод getPackages
следующим образом. Импортируйте любые классы, которые вам нужны, с помощью alt + enter
@Override protected List<ReactPackage> getPackages() { List<ReactPackage> packages = new PackageList(this).getPackages(); packages.add(new TurboReactPackage() { @Nullable @Override public NativeModule getModule(String name, ReactApplicationContext reactContext) { if (name.equals(NativeSampleModuleImpl.NAME)) { return new NativeSampleModuleImpl(reactContext); } else { return null; } } @Override public ReactModuleInfoProvider getReactModuleInfoProvider() { return () -> { final Map<String, ReactModuleInfo> moduleInfos = new HashMap<>(); moduleInfos.put( NativeSampleModuleImpl.NAME, new ReactModuleInfo( NativeSampleModuleImpl.NAME, NativeSampleModuleImpl.NAME, false, // canOverrideExistingModule false, // needsEagerInit true, // hasConstants false, // isCxxModule true // isTurboModule ) ); return moduleInfos; }; } }); return packages; }
Написание кода C++
Последний шаг, который нам нужно сделать, — настроить сторону C++. Начните с поиска файла Android.mk
по этому пути.
TurboModuleSample/android/app/src/main/jni/Android.mk
Затем раскомментируйте пути Codegen следующим образом:
include $(GENERATED_SRC_DIR)/codegen/jni/Android.mk
затем
LOCAL_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni LOCAL_SRC_FILES += $(wildcard $(GENERATED_SRC_DIR)/codegen/jni/*.cpp) LOCAL_EXPORT_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni
Внизу добавьте свою библиотеку. Он должен называться react_codegen_AppSpec
, он будет выглядеть так:
LOCAL_SHARED_LIBRARIES := \ react_codegen_AppSpec \ libfabricjni \ libfbjni \ libfolly_futures \ libfolly_json \ libglog \ libjsi \ libreact_codegen_rncore \ libreact_debug \ libreact_nativemodule_core \ libreact_render_componentregistry \ libreact_render_core \ libreact_render_debug \ libreact_render_graphics \ librrc_view \ libruntimeexecutor \ libturbomodulejsijni \ libyoga \
Затем в файле android/app/src/main/jni/MainApplicationModuleProvider.cpp
добавьте #include <AppSpec.h>
и раскомментируйте и замените следующие строки:
#include <AppSpec.h> .... auto module = AppSpec_ModuleProvider(moduleName, params); if (module != nullptr) { return module; }
На этом этапе давайте запустим yarn android
, чтобы убедиться, что приложение скомпилировано.
Триумфальное возвращение к React Native
Давайте закончим, проверив все. В любом месте вашего файла App.tsx
добавьте следующий код.
import NativeSampleModule from './js/NativeSampleModule'; ... const showMessage = () => { const message = NativeSampleModule.getHelloWorld('Daniel', 'Friyia'); alert(message); }; ... <Button title="Click here" onPress={showMessage} />
Когда вы нажимаете кнопку, вы должны увидеть всплывающее предупреждение с сообщением, которое мы создали в собственном слое.
Заключение
Надеюсь, вам понравилось это введение в TurboModules в React Native для Android. Достаточно скоро они уберут старый мост, поэтому нам будет важно быть в курсе того, как развиваются турбомодули. Пожалуйста, ознакомьтесь со второй частью, где я покажу вам, как заставить TurboModules и Codegen работать на iOS.
Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter и LinkedIn. Посетите наш Community Discord и присоединитесь к нашему Коллективу талантов.