Table of Contents
Inleiding tot Native Modules in React Native
React Native stelt ontwikkelaars in staat om cross-platform mobiele applicaties te bouwen met JavaScript en React. Terwijl het kader schepen met een rijke set van ingebouwde componenten voor gemeenschappelijke UI-elementen en kernapparaat API's, productie-apps vaak mogelijkheden voorbij React Native . Standaard JavaScript runtime. Native modules dienen als de brug tussen JavaScript en platform-specifieke code geschreven in Swift, Objective‐C, Kotlin, of Java. Ze ontgrendelen toegang tot hardware sensoren, systeemdiensten, derde partij SDK's, en prestatie-gevoelige functies die anders moeilijk of onmogelijk te implementeren met pure JavaScript. Begrijpen hoe te ambachtelijk en integreren inheemse modules is essentieel voor het bouwen van geavanceerde, feature-rijke toepassingen die echt eigen aanvoelen op zowel iOS als Android.
In deze gids, zullen we lopen door de hele levenscyclus van een inheemse module . . Van het opzetten van uw omgeving en het schrijven van platform code, tot het registreren van de module, het blootleggen van methoden, en het consumeren van hen van JavaScript. We zullen ook betrekking hebben op best practices, prestaties overwegingen, en real-world voorbeelden zoals toegang tot de camera, het omgaan met achtergrondtaken, en communicatie tussen draden. Tegen het einde, je zult een solide basis voor het uitbreiden van React Native ..
Inzicht in inheemse modules en de brug
In de kern, React Native . architectuur vertrouwt op een brug die serializes en deserializes berichten tussen de JavaScript-draad en de inheemse draden. Native modules zijn objecten die leven op de inheemse kant en zijn geregistreerd met de JavaScript runtime. Wanneer u een methode op een inheemse module van JS aanroepen, de brug stuurt een bericht naar de inheemse kant, voert de methode, en keert het resultaat (indien aanwezig) terug naar JS. Dit patroon kunt u gebruik maken van systeem API's . Bijvoorbeeld, toegang tot het apparaat gyroscope, het lezen van NFC-tags, of het versleutelen van gegevens met behulp van het platform .
Inheemse modules zijn bijzonder waardevol in de volgende scenario's:
- U moet een native bibliotheek (bijv. voor betaling verwerken, machine leren, of augmented reality) die geen JavaScript wrapper heeft integreren.
- U hebt een krachtige, lage-latency bewerkingen nodig die vertraagd zouden worden door de JS-draad (bv. beeldverwerking, audiosynthese).
- U moet toegang krijgen tot platformspecifieke functies die geen deel uitmaken van React Native. . Zoals de iOS HomeKit of Androids Biometric Prompt.
- U wilt code delen tussen een React Native app en een bestaande native codebase.
Voordat u in de implementatie duikt, is het belangrijk om te begrijpen dat inheemse modules geen magische kogel zijn . . . Ze vergroten de complexiteit, vereisen testen op elk platform, en kunnen zorgen introduceren over de veiligheid van de draad. Echter, wanneer ze bewust worden gebruikt, ze het mogelijk maken van het soort geavanceerde functionaliteit die uw app onderscheidt van eenvoudiger cross-platform concurrenten.
Uw ontwikkelingsomgeving instellen
Om native modules te maken, moet u de standaard React Native ontwikkeling omgeving voor zowel Android en iOS. Dit omvat Java / Kotlin tooling voor Android (Android Studio, Gradle, de Android SDK) en Xcode voor iOS met CocoaPods (of Swift Package Manager) voor afhankelijkheid management. Zorg ervoor dat u hebt geschreven React Native code voordat u probeert native modules .U moet comfortabel zijn met de basisprincipes van het creëren van een React Native project en het begrijpen van de bestandsstructuur.
De meeste ontwikkelaars starten met een React Native project dat via is gemaakt. Binnen het project worden native modules meestal geplaatst in de en directories. Voor modulariteit en herbruikbaarheid kunt u ook uw native module inpakken als een apart npm pakket . Veel community modules volgen dit patroon. We zullen ons richten op de in-project benadering voor duidelijkheid.
Een inheemse module aanmaken: De basis
Elke native module bestaat uit twee delen: de platformspecifieke implementatie (een voor Android, een voor iOS) en de JavaScript verbruikscode. Laten we de stappen voor elk platform afbreken.
Android (Kotlin/Java)
Op Android creëer je een klasse die zich uitstrekt en implementeer je de methoden die je wilt ontmaskeren. Elke methode die je moet oproepen vanuit JavaScript moet worden geannoteerd met en een retourtype hebben (of een callback/belofte gebruiken om gegevens terug te geven). Hier is een minimaal voorbeeld in 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)
}
}
}
Na het definiëren van de module, moet u het registreren met React Native . Pakketsysteem. Maak een pakketklasse die implementeert :
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()
}
}
Voeg tenslotte het pakket toe aan uw (of ) binnen de methode:
override fun getPackages(): List<ReactPackage> {
val packages = PackageList(this).packages
packages.add(MyNativePackage())
return packages
}
iOS (Swift/Objective-C)
Op iOS worden native modules meestal geschreven in Objective‐C of Swift. React Native verwacht een header bestand en implementatie die voldoet aan het protocol. Voor Swift moet je een overbruggingskop maken. Hieronder vindt u een Objective‐C voorbeeld:
// 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
Er is geen extra pakketregistratie nodig voor iOS . . React Native ontdekt automatisch klassen die overeenkomen met . Echter, u moet ervoor zorgen dat het .m bestand is gecompileerd in uw doel en dat u draait als u enige native afhankelijkheden toevoegt.
Voor Swift zijn de stappen gelijkaardig, maar vereisen ze de attribuut en een overbruggingskop. Een typische Swift implementatie ziet er als volgt uit:
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)
}
}
Vergeet niet in uw Objective‐C overbruggingskop te importeren: .
Inheemse modules van JavaScript consumeren
Zodra uw native module is geïmplementeerd en geregistreerd, kunt u toegang krijgen tot uw React Native JavaScript code via het object. De naam die u in (Android) of (iOS) geeft wordt de sleutel waaronder de module verschijnt. Bijvoorbeeld:
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));
U kunt ook gebruiken of gebeurtenis handlers indien nodig. Merk op dat de methodenaam in JavaScript moet exact overeenkomen met de methodenaam die u exporteerde in de native code. React Native kaarten hen 1:1, negeren van de Android methode annotation... naam parameter als u het overschrijven.
Voor methoden die meerdere parameters accepteren, gewoon doorgeven als argumenten . . de brug zal omgaan met serialization. Ondersteunde parametertypen omvatten , , , , (kaarten), en functies (oproepwoorden). Echter, het gebruik van Beloften via argument (Android) of de resolver/rejecter blokken (iOS) is de aanbevolen aanpak omdat het schoon integreert met React Native .
Geavanceerde communicatiepatronen
Terwijl basismethode calls betrekking hebben op veel use cases, geavanceerde functies vereisen vaak meer geavanceerde communicatie patronen. React Native ondersteunt verschillende mechanismen:
Terugbellen vs. Beloftes
Voor eenmalige operaties zijn Beloftes het schoonst. Voor continue datastromen (bv. sensorwaarden) heeft u de voorkeur aan terugroepen. Echter, terugbellen komt minder vaak voor in het moderne React Native omdat ze kunnen leiden tot terugroep-hell. Een beter patroon voor stromen is om gebeurtenissen uit te zenden van de oorspronkelijke kant naar JavaScript via de (iOS) of en ] (Android).
Uitzenden van gebeurtenissen van Inheems naar JavaScript
Om gegevens asynchroon van native code naar JS te sturen (bijvoorbeeld wanneer een native sensor wordt bijgewerkt), kunt u de event emitter singleton gebruiken. Op Android krijgt u een verwijzing naar en belt u :
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
.emit("onSensorUpdate", Arguments.createMap().apply {
putString("data", sensorValue)
})
Bij iOS, importeer en overschrijf ondersteunde gebeurtenissen:
@implementation MyNativeModule
RCT_EXPORT_MODULE();
- (NSArray<NSString *> *)supportedEvents {
return @[@"onSensorUpdate"];
}
// In your native method or delegate callback:
[self sendEventWithName:@"onSensorUpdate" body:@{@"data": sensorValue}];
@end
In JavaScript, abonneer je op het evenement met :
import { NativeEventEmitter, NativeModules } from 'react-native';
const { MyNativeModule } = NativeModules;
const eventEmitter = new NativeEventEmitter(MyNativeModule);
eventEmitter.addListener('onSensorUpdate', (event) => {
console.log('Sensor data:', event.data);
});
Vergeet niet om luisteraars te verwijderen wanneer het onderdeel ontkoppelt om geheugenlekken te voorkomen.
Thread Management en Performance
Standaard draait alle native module methode op de native thread pool, gescheiden van de UI thread. Dit is prima voor de meeste bewerkingen, maar als je de UI direct moet bijwerken vanuit je native module (bijv., het uitvoeren van een zware berekening en het bijwerken van een weergave), moet je werk verzenden naar de hoofdthread. Gebruik op Android ; gebruik op iOS .
Voor lang lopende achtergrondtaken (zoals database-synchronisatie of Bluetooth-scanning), kunt u overwegen om ] of terugroepen te gebruiken om te voorkomen dat u de brug blokkeert. U kunt ook extra draden in uw native module paaien, maar wees voorzichtig met de veiligheid van de draad . gedeelde staat moet worden gesynchroniseerd.
Prestatietip: minimaliseert de grootte van de data die door de brug worden doorgegeven. Grote arrays of binaire blobs (bijv. afbeeldingen) moeten worden behandeld met bestandspaden of verwijzingen in plaats van geserialiseerd in JSON.
Voorbeelden van de reële wereld
Om de concepten te consolideren, laten we twee gemeenschappelijke gebruikscases onderzoeken waar native modules onmisbaar zijn.
Cameratoegang
React Native heeft een ingebouwde maar bevat geen camera op laag niveau API. Een native module kan het platform chips camera . Bijvoorbeeld, Android .. API of iOS .. . Uw module kan methoden blootleggen om de camera voorvertoning te openen, een foto te maken, en het beeld pad terug te keren naar JS. Dit is precies wat populaire bibliotheken als doen. Door het schrijven van uw eigen, heb je volledige controle over frame verwerking, flitsinstellingen en handmatige focus.
Bluetooth-communicatie met lage energie (BLE)
Het verbinden met BLE randapparatuur (bijvoorbeeld hartslagmonitors, bakens) vereist inheemse systeem API's. Een native module kan scannen op apparaten, verbinding maken, diensten ontdekken en lees-/schrijfkenmerken. Omdat BLE operaties asynchrone zijn en vaak terugroepen omvatten, is het uitzenden van gebeurtenissen (zoals of ) het natuurlijke patroon. Er bestaan verschillende open-source BLE modules, maar het bouwen van je eigen zorgt ervoor dat je alleen de functionaliteit die je app nodig heeft blootlegt en geeft je controle over threading.
Beste praktijken en valkuilen
- Schrijf eenheid testen op native code. Zowel Android Studio en Xcode bieden testkaders (JUnit, XCTest). Test uw module ..methoden in isolatie voordat u integreren met React Native.
- Handle permissies sierlijk. Veel inheemse modules vereisen runtime permissies (camera, locatie, Bluetooth). React Native .. werkt voor Android, maar voor iOS moet je mogelijk toestemmingen aanvragen vanuit je eigen module of gebruik maken van een bibliotheek als . Nooit aannemen dat er toestemmingen worden verleend; afwijzing behandelen.
- Houd het bruglicht. Vermijd vaak passeren van grote objecten. Als u hogefrequentiegegevens moet streamen (bv. sensor op 100Hz), overweeg dan batching updates of overstappen naar een model waar native code gegevens pre-processeert en alleen geaggregeerde resultaten stuurt.
- Documenteer uw native module. Gebruik JSDoc of een README om elke methode, parameters, retourwaarden en platformverschillen te beschrijven. Dit is cruciaal wanneer andere teamleden of de open-source community uw module gebruiken.
- Gebruik pas nadat de app is geïnitialiseerd.[ Omdat inheemse modules vertrouwen op de brug klaar is, kan toegang tot hen te vroeg (bijvoorbeeld in een globale context) resulteren in ]. Altijd toegang krijgen tot hen binnen een component of na die wacht op de brug.
- Gebruik bestaande modules indien mogelijk. Het React Native ecosysteem heeft duizenden pakketten. Voordat je je eigen native module schrijft, zoek naar bestaande modules. Als je een module vindt die bijna aan je behoeften voldoet, overweeg dan om bij te dragen in plaats van het wiel opnieuw uit te vinden.
- Bekijk TurboModules voor nieuwe projecten. Vanaf React Native 0.68 biedt de nieuwe architectuur met TurboModules betere prestaties en JavaScript-native geheugendeling. Als je een nieuwe app start, beoordeel dan met TurboModules (via de Nieuwe Architectuur) in plaats van met de oude brug.
Externe middelen
Om dieper in de ontwikkeling van de native module te duiken, raadpleeg de officiële React Native documentatie over native modules. Voor platformspecifieke begeleiding, de Android developer guides[ en Apple...Developer documentatie] geeft gezaghebbende referenties. Daarnaast biedt de community-maintenance ] React Native Community GitHub organisatie[ host veel goed geteste native modules die je als voorbeelden kunt bestuderen.
Conclusie
Native modules zijn een krachtig hulpmiddel in de React Native ontwikkelaars arsenaal, waardoor toegang tot de volledige breedte van platform mogelijkheden. Hoewel ze toevoegen aan extra complexiteit . . vereist kennis van Java/Kotlin of Swift/Objective-C, zorgvuldige draadbeheer, en rigoureuze testen . . de uitbetaling is de mogelijkheid om geavanceerde functies die anders onmogelijk zou zijn te leveren. Door het volgen van de patronen beschreven in deze gids . . het creëren van een goed gestructureerde inheemse module, met behulp van Promeses en evenementen voor schone async communicatie, en door te gaan met de beste praktijken rond machtigingen en prestaties . U kunt vertrouwen uitbreiden React Native over de ingebouwde grenzen.
Start klein: bouw een eenvoudige rekenmachine module die twee getallen vermenigvuldigt en het resultaat teruggeeft. Daarna afstudeer aan meer complexe modules zoals een batterijniveau indicator of een aangepaste afbeelding filter. Elke native module die u maakt verdiept uw begrip van het platform en maakt u een veelzijdigere mobiele ontwikkelaar.