From bb4c1a1bc98f125b90560374ea4e058194d21d6d Mon Sep 17 00:00:00 2001 From: Marius Petcu Date: Mon, 4 Jul 2016 00:43:48 +0300 Subject: [PATCH] Make progress notifications throttle configurable --- API.md | 11 +++++++ .../ReactNativeMapboxGLModule.java | 12 ++++++- index.js | 7 +++- ios/RCTMapboxGL/RCTMapboxGLManager.h | 1 + ios/RCTMapboxGL/RCTMapboxGLManager.m | 33 +++++++++++-------- 5 files changed, 49 insertions(+), 15 deletions(-) diff --git a/API.md b/API.md index a03c2e7..8d357fb 100644 --- a/API.md +++ b/API.md @@ -405,6 +405,17 @@ const subscription = Mapbox.addOfflinePackProgressListener(progressObject => { subscription.remove(); ``` +Due to high volume, progress notifications are throttled so as not to starve the +run loop and make the JS thread unresponsive. + +By default, you'll get at most one progress notification per pack each 300 ms. + +You can configure this interval with: + +```javascript +Mapbox.setOfflinePackProgressThrottleInterval(milis); +``` + #### Subscribing to error events ```javascript diff --git a/android/src/main/java/com/mapbox/reactnativemapboxgl/ReactNativeMapboxGLModule.java b/android/src/main/java/com/mapbox/reactnativemapboxgl/ReactNativeMapboxGLModule.java index 0a4ebd2..21dcd40 100644 --- a/android/src/main/java/com/mapbox/reactnativemapboxgl/ReactNativeMapboxGLModule.java +++ b/android/src/main/java/com/mapbox/reactnativemapboxgl/ReactNativeMapboxGLModule.java @@ -34,6 +34,7 @@ import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeArray; import com.facebook.react.modules.core.RCTNativeAppEventEmitter; +import com.facebook.react.uimanager.annotations.ReactProp; import com.mapbox.mapboxsdk.MapboxAccountManager; import com.mapbox.mapboxsdk.constants.MyLocationTracking; import com.mapbox.mapboxsdk.constants.MyBearingTracking; @@ -57,6 +58,8 @@ public class ReactNativeMapboxGLModule extends ReactContextBaseJavaModule { private ReactApplicationContext context; private ReactNativeMapboxGLPackage aPackage; Handler mainHandler; + private int throttleInterval = 300; + private static boolean initialized = false; public ReactNativeMapboxGLModule(ReactApplicationContext reactContext, ReactNativeMapboxGLPackage thePackage) { @@ -198,7 +201,7 @@ public class ReactNativeMapboxGLModule extends ReactContextBaseJavaModule { fireUpdateEvent(); } } - }, 100); + }, throttleInterval); } @Override @@ -519,4 +522,11 @@ public class ReactNativeMapboxGLModule extends ReactContextBaseJavaModule { } }); } + + // Offline throttle control + + @ReactMethod + public void setOfflinePackProgressThrottleInterval(int milis) { + throttleInterval = milis; + } } \ No newline at end of file diff --git a/index.js b/index.js index b8d783a..30eb514 100644 --- a/index.js +++ b/index.js @@ -116,6 +116,10 @@ function removeOfflinePack(packName, callback) { return promise; } +function setOfflinePackProgressThrottleInterval(milis) { + MapboxGLManager.setOfflinePackProgressThrottleInterval(milis); +} + function addOfflinePackProgressListener(handler) { let _handler = handler; if (Platform.OS === 'android') { @@ -404,7 +408,8 @@ const Mapbox = { addOfflinePack, getOfflinePacks, removeOfflinePack, addOfflinePackProgressListener, addOfflineMaxAllowedTilesListener, - addOfflineErrorListener + addOfflineErrorListener, + setOfflinePackProgressThrottleInterval }; module.exports = Mapbox; diff --git a/ios/RCTMapboxGL/RCTMapboxGLManager.h b/ios/RCTMapboxGL/RCTMapboxGLManager.h index f438148..18f369c 100644 --- a/ios/RCTMapboxGL/RCTMapboxGLManager.h +++ b/ios/RCTMapboxGL/RCTMapboxGLManager.h @@ -13,5 +13,6 @@ NSMutableSet * _throttledPacks; NSMutableArray * _packRequests; NSMutableSet * _removedPacks; + int _throttleInterval; } @end \ No newline at end of file diff --git a/ios/RCTMapboxGL/RCTMapboxGLManager.m b/ios/RCTMapboxGL/RCTMapboxGLManager.m index b0a2973..03092d9 100644 --- a/ios/RCTMapboxGL/RCTMapboxGLManager.m +++ b/ios/RCTMapboxGL/RCTMapboxGLManager.m @@ -140,6 +140,7 @@ RCT_EXPORT_METHOD(setAccessToken:(nonnull NSString *)accessToken) _recentPacks = [NSMutableSet new]; _throttledPacks = [NSMutableSet new]; _removedPacks = [NSMutableSet new]; + _throttleInterval = 300; // Setup pack array loading notifications [[MGLOfflineStorage sharedOfflineStorage] addObserver:self forKeyPath:@"packs" options:0 context:NULL]; @@ -198,6 +199,16 @@ RCT_EXPORT_METHOD(setAccessToken:(nonnull NSString *)accessToken) @"maximumResourcesExpected": @(progress.maximumResourcesExpected) }; [_bridge.eventDispatcher sendAppEventWithName:@"MapboxOfflineProgressDidChange" body:event]; + + [_recentPacks addObject:pack]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, _throttleInterval * NSEC_PER_MSEC), dispatch_get_main_queue(), ^{ + [_recentPacks removeObject:pack]; + if ([_throttledPacks containsObject:pack]) { + [_throttledPacks removeObject:pack]; + [self firePackProgress:pack]; + } + }); } - (void)flushThrottleForPack:(MGLOfflinePack*)pack { @@ -225,16 +236,7 @@ RCT_EXPORT_METHOD(setAccessToken:(nonnull NSString *)accessToken) return; } - [_recentPacks addObject:pack]; [self firePackProgress:pack]; - - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 100 * NSEC_PER_MSEC), dispatch_get_main_queue(), ^{ - [_recentPacks removeObject:pack]; - if ([_throttledPacks containsObject:pack]) { - [_throttledPacks removeObject:pack]; - [self firePackProgress:pack]; - } - }); } - (void)offlinePackDidReceiveMaximumAllowedMapboxTiles:(NSNotification *)notification { @@ -257,7 +259,7 @@ RCT_EXPORT_METHOD(setAccessToken:(nonnull NSString *)accessToken) NSDictionary *event = @{ @"name": userInfo[@"name"], @"error": [error localizedDescription] }; - + [_bridge.eventDispatcher sendAppEventWithName:@"MapboxOfflineError" body:event]; } @@ -334,13 +336,13 @@ RCT_REMAP_METHOD(addOfflinePack, @"countOfResourcesExpected": @(pack.progress.countOfResourcesExpected), @"maximumResourcesExpected": @(pack.progress.maximumResourcesExpected) }]; } - + return callbackArray; } RCT_REMAP_METHOD(getOfflinePacks, - resolver:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { dispatch_async(dispatch_get_main_queue(), ^{ NSMutableArray* callbackArray = [NSMutableArray new]; @@ -398,6 +400,11 @@ RCT_REMAP_METHOD(removeOfflinePack, }); } +RCT_EXPORT_METHOD(setOfflinePackProgressThrottleInterval:(nonnull NSNumber *)milis) +{ + _throttleInterval = [milis intValue]; +} + // View methods RCT_EXPORT_METHOD(spliceAnnotations:(nonnull NSNumber *)reactTag