Native发送大量的数据给JS
问题:
RCTRootView 有个appProperties传递数据,但是当数据很大的时候将变得非常缓慢。
解决方法:
通过通知携带大数据,性能得到保证。
代码:
RNViewController:
override func viewDidLoad() {
super.viewDidLoad()
_ = NotificationCenter.default.addObserver(forName: NSNotification.Name.RCTJavaScriptDidLoad,
object: nil, queue: nil) { _ in
RNViewController.javascriptLoaded = true
}
errorHandler = ErrorHandler(
proposer: MyAppMainProposer()
)
errorHandler.executor = self
}
deinit {
NotificationCenter.default.removeObserver(self)
}
// Used to changed data async. Usually for big data
func notifyDataChanged(data: Parameters, completion: (() -> Void)?) {
DispatchQueue.global().async {
self.notifyDataChangedInternal(data: data, completion: completion)
}
}
private func notifyDataChangedInternal(data: Parameters, completion: (() -> Void)?) {
// Make sure Javascript loaded
while !RNViewController.javascriptLoaded {
logger.info("Waiting for Javascript Loaded")
// Sleep on Global Thread
Thread.sleep(forTimeInterval: 0.2)
}
// Make sure UI first render
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
AppNativeEventEmitter.sharedInstance().notifyDataChanged(onJS: data)
completion?()
}
}
AppNativeEventEmitter.m
#import "AppNativeEventEmitter.h"
@implementation AppNativeEventEmitter
NSString * const kOnLeftBarButtonClicked = @"onLeftBarButtonClicked";
NSString * const kOnRightBarButtonClicked = @"onRightBarButtonClicked";
NSString * const kOnDataChanged = @"onDataChanged";
NSString * const kDataEventCallback = @"DataEventCallback";
+ (instancetype)sharedInstance
{
return [[AppNativeEventEmitter alloc] init];
}
// It is very important making a singleton object.
+(id)allocWithZone:(NSZone *)zone
{
static AppNativeEventEmitter *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [super allocWithZone:zone];
});
return sharedInstance;
}
RCT_EXPORT_MODULE();
+ (BOOL)requiresMainQueueSetup {
return YES;
}
- (NSDictionary *)constantsToExport {
return @{};
}
- (NSArray<NSString *> *)supportedEvents {
return @[
(NSString *)kDataEventCallback
];
}
- (void)callLeftBarButtonClickedOnJS {
[self callDataEventCallbackOnJS:@{
@"eventType": kOnLeftBarButtonClicked
}];
}
- (void)callRightBarButtonClickedOnJS {
[self callDataEventCallbackOnJS:@{
@"eventType": kOnRightBarButtonClicked
}];
}
- (void)notifyDataChangedOnJS:(NSDictionary *)data {
[self callDataEventCallbackOnJS:@{
@"eventType": kOnDataChanged,
@"data": data
}];
}
- (void)callDataEventCallbackOnJS: (NSDictionary *)parameters {
[self callJSWithEvent:kDataEventCallback parameters:parameters];
}
- (void)callJSWithEvent:(NSString *) eventName parameters:(NSDictionary *)parameters {
[self sendEventWithName:eventName body:parameters];
}
- (void)startObserving {
}
- (void)stopObserving {
}
@end
// AppNativeEventEmitter.h
#import <Foundation/Foundation.h>
#import <React/RCTEventEmitter.h>
NS_ASSUME_NONNULL_BEGIN
@interface AppNativeEventEmitter : RCTEventEmitter
+ (instancetype)sharedInstance;
- (void)callLeftBarButtonClickedOnJS;
- (void)callRightBarButtonClickedOnJS;
- (void)notifyDataChangedOnJS:(NSDictionary *)data;
- (void)callDataEventCallbackOnJS: (NSDictionary *)parameters;
- (void)callJSWithEvent:(NSString *) eventName parameters:(NSDictionary *)parameters;
@end
NS_ASSUME_NONNULL_END
JS 端:
RNBaseComponent.js
import React from 'react';
import {
Platform,
NativeEventEmitter,
DeviceEventEmitter,
NativeModules
} from 'react-native';
import DataEventType from '../constants/dataEventType';
const { AppNativeEventEmitter } = NativeModules;
export default class RNBaseComponent extends React.Component {
componentDidMount = () => {
const emitter = Platform.OS === 'ios' ? new NativeEventEmitter(AppNativeEventEmitter) : DeviceEventEmitter;
this.onDataEventSubscription = emitter.addListener('DataEventCallback',
async (params) => {
await this.handleDataEvent(params);
});
}
componentWillUnmount() {
if (this.onDataEventSubscription) this.onDataEventSubscription.remove();
}
handleDataEvent = async (params) => {
const { eventType, data } = params;
if (eventType === DataEventType.onLeftBarButtonClicked) {
await this.onLeftBarButtonEvent(params);
} else if (eventType === DataEventType.onRightBarButtonClicked) {
await this.onRightBarButtonEvent(params);
} else if (eventType === DataEventType.onDataChanged) {
await this.onDataChanged(data);
} else {
await this.onDataEventCallback(eventType, data);
}
}
onDataChanged = async (data) => {
console.log(`onDataChanged ${data ? 'data' : 'no data'}`);
}
onLeftBarButtonEvent = async (params) => {
console.log(`onLeftBarButtonEvent ${params}`);
}
onRightBarButtonEvent = async (params) => {
console.log(`onRightBarButtonEvent ${params}`);
}
// customized event
onDataEventCallback = async (eventType, data) => {
console.log(`onDataEventCallback ${eventType} ${data}`);
}
}
JS页面继承自RNBaseComponent去覆盖onDataChanged。