Flush UI blocks as soon as they're accumulated

Summary:
public

Currently, we wait to invoke `-flushUIBlocks` until the JavaScript batch to native has completed. This means we may be waiting an unnecessarily long time to perform view hierarchy changes and prop changes.

By instead invoking this after each chunk of enqueued UI blocks, we can perform some updates more eagerly, increasing our utilization of the main thread while splitting up the amount of time we spend running upon it.

This shouldn't affect layout, which is still tied to `-batchDidComplete`, so any visual inconsistencies should be limited to prop changes, which seems acceptable for the dramatic improvement in performance.

Reviewed By: javache

Differential Revision: D2658552

fb-gh-sync-id: 6d4560e21d7da1b02d2f30d1860d60735f11c4b5
This commit is contained in:
Justin Spahr-Summers 2015-12-02 05:12:17 -08:00 committed by facebook-github-bot-4
parent 802aef9509
commit c25c98c00c
4 changed files with 38 additions and 0 deletions

View File

@ -720,6 +720,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
if (buffer != nil && buffer != (id)kCFNull) { if (buffer != nil && buffer != (id)kCFNull) {
_wasBatchActive = YES; _wasBatchActive = YES;
[self handleBuffer:buffer]; [self handleBuffer:buffer];
[self partialBatchDidFlush];
} }
if (batchEnded) { if (batchEnded) {
@ -800,6 +801,17 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
} }
} }
- (void)partialBatchDidFlush
{
for (RCTModuleData *moduleData in _moduleDataByID) {
if (moduleData.hasInstance && [moduleData.instance respondsToSelector:@selector(partialBatchDidFlush)]) {
[self dispatchBlock:^{
[moduleData.instance partialBatchDidFlush];
} queue:moduleData.methodQueue];
}
}
}
- (void)batchDidComplete - (void)batchDidComplete
{ {
// TODO: batchDidComplete is only used by RCTUIManager - can we eliminate this special case? // TODO: batchDidComplete is only used by RCTUIManager - can we eliminate this special case?

View File

@ -235,4 +235,12 @@ RCT_EXTERN void RCTRegisterModule(Class); \
*/ */
- (void)batchDidComplete; - (void)batchDidComplete;
/**
* Notifies the module that the active batch of JS method invocations has been
* partially flushed.
*
* This occurs before -batchDidComplete, and more frequently.
*/
- (void)partialBatchDidFlush;
@end @end

View File

@ -77,6 +77,17 @@ RCT_EXTERN NSString *const RCTUIManagerRootViewKey;
*/ */
+ (UIView *)JSResponder; + (UIView *)JSResponder;
/**
* Normally, UI changes are not applied until the complete batch of method
* invocations from JavaScript to native has completed.
*
* Setting this to YES will flush UI changes sooner, which could potentially
* result in inconsistent UI updates.
*
* The default is NO (recommended).
*/
@property (atomic, assign) BOOL unsafeFlushUIChangesBeforeBatchEnds;
@end @end
/** /**

View File

@ -880,6 +880,13 @@ RCT_EXPORT_METHOD(findSubviewIn:(nonnull NSNumber *)reactTag atPoint:(CGPoint)po
}]; }];
} }
- (void)partialBatchDidFlush
{
if (self.unsafeFlushUIChangesBeforeBatchEnds) {
[self flushUIBlocks];
}
}
- (void)batchDidComplete - (void)batchDidComplete
{ {
// Gather blocks to be executed now that all view hierarchy manipulations have // Gather blocks to be executed now that all view hierarchy manipulations have