Advanced Manufacturing Techniques
How to Use React Native with Native Modules for Advanced Features
Table of Contents
Introdução aos Módulos Nativos em Reagir Nativo
Reagir Native capacita os desenvolvedores a criar aplicativos móveis multiplataforma usando JavaScript e Reagir. Enquanto o framework envia um rico conjunto de componentes integrados para elementos de interface comuns e APIs de dispositivos principais, aplicativos de produção muitas vezes requerem recursos além do tempo padrão de execução JavaScript do React Native. Os módulos nativos servem como ponte entre JavaScript e código específico de plataforma escrito em Swift, Objective-C, Kotlin ou Java. Eles desbloqueiam o acesso a sensores de hardware, serviços de sistema, SDKs de terceiros e recursos sensíveis ao desempenho que de outra forma seriam difíceis ou impossíveis de implementar com JavaScript puro. Entender como criar e integrar módulos nativos é essencial para a construção de aplicativos avançados, ricos em recursos que se sintam realmente nativos tanto no iOS quanto no Android.
Neste guia, percorreremos todo o ciclo de vida de um módulo nativo – desde a configuração do seu ambiente e o código da plataforma de escrita, até o registro do módulo, expondo métodos e consumindo-os do JavaScript. Também cobriremos as melhores práticas, considerações de desempenho e exemplos do mundo real, como acessar a câmera, lidar com tarefas de fundo e comunicar entre threads. No final, você terá uma base sólida para ampliar as capacidades do React Native com seus próprios módulos nativos.
Compreender os Módulos Nativos e a Ponte
No seu núcleo, a arquitetura do React Native depende de uma ponte que serializa e deserializa mensagens entre o tópico JavaScript e os tópicos nativos. Os módulos nativos são objetos que vivem do lado nativo e estão registrados com o tempo de execução do JavaScript. Quando você chama um método em um módulo nativo do JS, a ponte envia uma mensagem para o lado nativo, executa o método e retorna o resultado (se houver) de volta para o JS. Este padrão permite que você use APIs do sistema de alavancagem – por exemplo, acessando o giroscópio do dispositivo, lendo etiquetas NFC ou criptografando dados usando o enclave seguro da plataforma – que não são expostos através das bibliotecas padrão do React Native.
Os módulos nativos são particularmente valiosos nos seguintes cenários:
- Você precisa integrar uma biblioteca nativa (por exemplo, para processamento de pagamento, aprendizado de máquina ou realidade aumentada) que não tenha wrapper JavaScript.
- Você precisa de operações de alto desempenho e baixa latência que seriam retardadas pelo fio JS (por exemplo, processamento de imagem, síntese de áudio).
- Você deve acessar recursos específicos de plataforma que não fazem parte do núcleo do React Native – como o iOS HomeKit ou o Prompt Biométrico do Android.
- Você deseja compartilhar código entre um aplicativo React Native e uma base de código nativa existente.
Antes de mergulhar na implementação, é importante entender que os módulos nativos não são uma “bala mágica” – aumentam a complexidade, exigem testes em cada plataforma e podem introduzir preocupações de segurança de roscas. No entanto, quando usados criteriosamente, permitem o tipo de funcionalidade avançada que diferencia o seu aplicativo de concorrentes multiplataforma mais simples.
Configurando seu ambiente de desenvolvimento
Para criar módulos nativos, você precisa do ambiente de desenvolvimento nativo padrão React para Android e iOS. Isto inclui ferramentas Java/Kotlin para Android (Android Studio, Gradle, o Android SDK) e Xcode para iOS com CocoaPods (ou Swift Package Manager) para gerenciamento de dependência. Certifique-se de ter escrito Reagir código nativo antes de tentar módulos nativos – você deve estar confortável com o básico de criar um projeto nativo React e entender a estrutura de arquivos.
A maioria dos desenvolvedores começa com um projeto React Native criado via . Dentro do projeto, os módulos nativos são geralmente colocados dentro dos diretórios e . Para modularidade e reutilizabilidade, você também pode embrulhar seu módulo nativo como um pacote npm separado – muitos módulos comunitários seguem este padrão. Vamos focar na abordagem dentro do projeto para clareza.
Criando um Módulo Nativo: Os Básicos
Cada módulo nativo é composto por duas partes: a implementação específica da plataforma (uma para Android, outra para iOS) e o código de consumo JavaScript. Vamos quebrar as etapas para cada plataforma.
Android (Kotlin/Java)
No Android, você cria uma classe que se estende e implementa os métodos que deseja expor. Cada método que deve ser chamado a partir do JavaScript deve ser anotado com e ter um tipo de retorno (ou usar um callback/promessa para retornar dados). Aqui está um exemplo mínimo em Kotlin:
package com.yourapp
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.Promise
class MyNativeModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
override fun getName(): String = "MyNativeModule"
@ReactMethod
fun doSomething(param: String, promise: Promise) {
try {
// Perform native work here
val result = "Hello from Kotlin! Received: $param"
promise.resolve(result)
} catch (e: Exception) {
promise.reject("ERROR", e.message)
}
}
}
Depois de definir o módulo, você deve registrá-lo com o sistema de pacotes React Native. Crie uma classe de pacote que implementa :
package com.yourapp
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ViewManager
class MyNativePackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
return listOf(MyNativeModule(reactContext))
}
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
return emptyList()
}
}
Finalmente, adicione o pacote ao seu (ou ]] dentro do método :
override fun getPackages(): List<ReactPackage> {
val packages = PackageList(this).packages
packages.add(MyNativePackage())
return packages
}
iOS (Swift/Objetivo-C)
No iOS, os módulos nativos são tipicamente escritos em Objective-C ou Swift. React Native espera um arquivo de cabeçalho e implementação que esteja de acordo com o protocolo . Para Swift, você deve criar um cabeçalho de ponte. Aqui está um exemplo de Objective-C:
// MyNativeModule.h
#import <React/RCTBridgeModule.h>
@interface MyNativeModule : NSObject <RCTBridgeModule>
@end
// MyNativeModule.m
#import "MyNativeModule.h"
#import <React/RCTLog.h>
@implementation MyNativeModule
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(doSomething:(NSString *)param
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
NSString *result = [NSString stringWithFormat:@"Hello from iOS! Received: %@", param];
resolve(result);
}
@end
Não é necessário registro de pacotes adicionais para iOS – Reagir Nativo automaticamente descobre classes que se conformam com . No entanto, você deve garantir que o arquivo .m é compilado em seu alvo e que você executa se você adicionar qualquer dependência nativa.
Para Swift, os passos são semelhantes, mas requerem o atributo e um cabeçalho de ponte. Uma implementação típica Swift se parece com isto:
import Foundation
@objc(MyNativeModule)
class MyNativeModule: NSObject {
@objc
func doSomething(_ param: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
let result = "Hello from Swift! Received: \(param)"
resolve(result)
}
}
Lembre-se de importar no seu cabeçalho de ligação Objective-C: .
Consumindo módulos nativos do JavaScript
Uma vez implementado e registrado o seu módulo nativo, você pode acessá- lo no seu código JavaScript nativo Reagir através do objeto . O nome que você fornece em (Android) ou (iOS) torna- se a chave sob a qual o módulo aparece. Por exemplo:
import { NativeModules } from 'react-native';
const { MyNativeModule } = NativeModules;
// Calling an exported method
MyNativeModule.doSomething('React Native')
.then(result => console.log(result))
.catch(error => console.error(error));
Você também pode usar ou manipuladores de eventos conforme necessário. Observe que o nome do método no JavaScript deve corresponder exatamente ao nome do método que você exportou no código nativo. Reaja mapas nativos deles 1:1, ignorando o parâmetro de nome da anotação do método Android se você sobrepor a ele.
Para métodos que aceitam múltiplos parâmetros, simplesmente passe-os como argumentos – a ponte irá lidar com serialização. Os tipos de parâmetros suportados incluem , , , , , (mapas), e funções (challbacks). No entanto, usando Promises via o argumento ] (Android) ou os blocos de resolução/rejeitor (iOS) é a abordagem recomendada porque ele se integra de forma limpa com a natureza assíncrona do Reagir Nativo.
Padrões de Comunicação Avançados
Embora as chamadas de método básico cubram muitos casos de uso, recursos avançados muitas vezes requerem padrões de comunicação mais sofisticados. Reagir Nativo suporta vários mecanismos:
Chamadas contra Promessas
Para operações únicas, as Promessas são as mais limpas. Para fluxos de dados contínuos (por exemplo, leituras de sensores), você pode preferir callbacks. No entanto, callbacks são menos comuns no React Native moderno porque podem levar ao callback-hell. Um padrão melhor para fluxos é emitir eventos do lado nativo para o JavaScript através do (iOS) ou e (Android).
Emitindo eventos de nativos para JavaScript
Para enviar dados assíncronos do código nativo para JS (por exemplo, quando um sensor nativo atualiza), você pode usar o emissor de eventos singleton. No Android, obtenha uma referência para o e chame :
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
.emit("onSensorUpdate", Arguments.createMap().apply {
putString("data", sensorValue)
})
No iOS, importar e sobrepor eventos suportados:
@implementation MyNativeModule
RCT_EXPORT_MODULE();
- (NSArray<NSString *> *)supportedEvents {
return @[@"onSensorUpdate"];
}
// In your native method or delegate callback:
[self sendEventWithName:@"onSensorUpdate" body:@{@"data": sensorValue}];
@end
No JavaScript, subscreva-se ao evento usando :
import { NativeEventEmitter, NativeModules } from 'react-native';
const { MyNativeModule } = NativeModules;
const eventEmitter = new NativeEventEmitter(MyNativeModule);
eventEmitter.addListener('onSensorUpdate', (event) => {
console.log('Sensor data:', event.data);
});
Não se esqueça de remover os ouvintes quando o componente desmonta para evitar vazamentos de memória.
Gestão e Desempenho do Tópico
Por padrão, todas as chamadas de módulo nativo são executadas no pool de thread nativo, separadas do tópico UI. Isso é bom para a maioria das operações, mas se você precisar atualizar a interface diretamente do seu módulo nativo (por exemplo, realizando um cálculo pesado e atualizando uma visualização), você deve enviar o trabalho para o tópico principal. No Android, use ; no iOS, use .
Para tarefas de fundo de longa duração (como sincronização de banco de dados ou varredura Bluetooth), considere usar ou callbacks para evitar bloquear a ponte. Você também pode gerar threads adicionais dentro do seu módulo nativo, mas seja cauteloso com a segurança de threads – o estado compartilhado deve ser sincronizado.
Dica de desempenho: minimizar o tamanho dos dados passados através da ponte. Grandes arrays ou blobs binários (por exemplo, imagens) devem ser manuseados com caminhos de arquivos ou referências em vez de serializados em JSON.
Exemplos do mundo real
Para solidificar os conceitos, vamos examinar dois casos de uso comum onde os módulos nativos são indispensáveis.
Acesso à câmera
React Native tem uma API integrada mas não inclui uma API de câmara de baixo nível. Um módulo nativo pode envolver a câmera da plataforma – por exemplo, a API do Android ou a API do iOS . O seu módulo pode expor métodos para abrir a antevisão da câmera, capturar uma foto e retornar o caminho da imagem para o JS. Isto é exatamente o que as bibliotecas populares como ] fazem. Ao escrever o seu próprio, você tem controle total sobre o processamento de quadros, configurações flash e foco manual.
Comunicação Bluetooth de baixa energia (BLE)
A ligação aos periféricos do BLE (por exemplo, monitores de frequência cardíaca, faróis) requer APIs de sistemas nativas. Um módulo nativo pode procurar dispositivos, ligar, descobrir serviços e ler/escrever características. Porque as operações do BLE são assíncronas e envolvem frequentemente chamadas de retorno, emitindo eventos (como ] ou ) é o padrão natural. Existem vários módulos de BLE de código aberto, mas a construção dos seus próprios garante que você só expõe a funcionalidade que a sua aplicação necessita e lhe dá controlo sobre a threading.
Melhores Práticas e Arremessos
- Escreva testes unitários para código nativo. Tanto o Android Studio quanto o Xcode fornecem frameworks de teste (JUnit, XCTest). Teste os métodos do seu módulo de forma isolada antes de integrar com o React Native.
- Permissões de mão graciosamente. Muitos módulos nativos requerem permissões de tempo de execução (câmera, localização, Bluetooth). Reagir Nativo funciona para Android, mas para iOS você pode precisar solicitar permissões de dentro do seu módulo nativo ou usar uma biblioteca como . Nunca assuma que permissões são concedidas; lidar com rejeição.
- Mantenha a luz da ponte. Evite passar objetos grandes com frequência. Se você precisar transmitir dados de alta frequência (por exemplo, sensor a 100Hz), considere atualizações de loteamento ou mudar para um modelo onde o código nativo pré-processa dados e envia apenas resultados agregados.
- Documente cuidadosamente a API do seu módulo nativo. Use JSDoc ou um README para descrever cada método, seus parâmetros, valores de retorno e diferenças de plataforma.Isso é crucial quando outros membros da equipe ou a comunidade de código aberto consomem seu módulo.
- Use só depois de inicializado o aplicativo. Porque os módulos nativos dependem da ponte estar pronta, acessá-los muito cedo (por exemplo, em um contexto global) pode resultar em . Acesse-os sempre dentro de um componente ou depois de um que espera pela ponte.
- Aproveite os módulos existentes quando possível. O ecossistema nativo React tem milhares de pacotes. Antes de escrever seu próprio módulo nativo, procure por módulos existentes. Se você encontrar um módulo que quase se adapte às suas necessidades, considere contribuir em vez de reinventar a roda.
- Considere TurboModules para novos projetos. A partir de React Native 0.68, a nova arquitetura com TurboModules oferece melhor desempenho e partilha de memória JavaScript-native. Se você está começando uma nova aplicação, avalie usando TurboModules (através da Nova Arquitetura) em vez da antiga ponte.
Recursos externos
Para mergulhar mais profundamente no desenvolvimento de módulos nativos, consulte o Reagir documentação nativa em módulos nativos. Para orientação específica de plataforma, os guias de desenvolvimento Android[] e A documentação de desenvolvimento da Apple[ fornecem referências autoritárias. Além disso, a organização Comunidade Nativa do GitHub [ recebe muitos módulos nativos bem testados que você pode estudar como exemplos.
Conclusão
Os módulos nativos são uma ferramenta poderosa no arsenal do desenvolvedor React Native, permitindo o acesso à totalidade das capacidades da plataforma. Embora introduzam complexidade adicional – exigindo conhecimento de Java/Kotlin ou Swift/Objetivo-C, gestão cuidadosa de threads e testes rigorosos – o pagamento é a capacidade de fornecer recursos avançados que de outra forma seriam impossíveis. Seguindo os padrões descritos neste guia – criando um módulo nativo bem estruturado, usando Promessas e eventos para limpar a comunicação assincronizada, e aderindo às melhores práticas em torno de permissões e desempenho – você pode seguramente estender Reagir Nativo além de seus limites embutidos.
Iniciar pequeno: crie um módulo de calculadora simples que multiplica dois números e retorna o resultado. Então classifique-se para módulos mais complexos, como um indicador de nível de bateria ou um filtro de imagem personalizado. Cada módulo nativo que você cria aprofunda sua compreensão da plataforma e torna você um desenvolvedor móvel mais versátil.