/// <summary> /// Adds a root view to the hierarchy. /// </summary> /// <param name="tag">The root view tag.</param> /// <param name="rootView">The root view.</param> /// <param name="themedRootContext">The React context.</param> public void AddRootView( int tag, SizeMonitoringCanvas rootView, ThemedReactContext themedRootContext) { // This is called on layout manager thread // Extract dispatcher var rootViewDispatcher = rootView.Dispatcher; // _dispatcherToOperationQueueInfo contains a mapping of CoreDispatcher to <UIViewOperationQueueInstance, # of ReactRootView instances>. // Operation queue instances are created lazily whenever an "unknown" CoreDispatcher is detected. Each operation queue instance // works together with one dedicated NativeViewHierarchyManager and one ReactChoreographer. // One operation queue is the "main" one: // - is coupled with the CoreApplication.MainView dispatcher // - drives animations in ALL views QueueInstanceInfo queueInfo; if (!_dispatcherToOperationQueueInfo.TryGetValue(rootViewDispatcher, out queueInfo)) { // Queue instance doesn't exist for this dispatcher, we need to create // Find the CoreApplicationView associated to the new CoreDispatcher CoreApplicationView foundView = CoreApplication.Views.First(v => v.Dispatcher == rootViewDispatcher); // Create new ReactChoreographer for this view/dispatcher. It will only be used for its DispatchUICallback services ReactChoreographer reactChoreographer = ReactChoreographer.CreateSecondaryInstance(foundView); queueInfo = new QueueInstanceInfo() { queueInstance = new UIViewOperationQueueInstance( _reactContext, new NativeViewHierarchyManager(_viewManagerRegistry, rootViewDispatcher, OnViewsDropped), reactChoreographer), rootViewCount = 1 }; // Add new tuple to map _dispatcherToOperationQueueInfo.Add(rootViewDispatcher, queueInfo); if (_active) { // Simulate an OnResume from the correct dispatcher thread // (OnResume/OnSuspend/OnDestroy have this thread affinity, all other methods do enqueuings in a thread safe manner) DispatcherHelpers.RunOnDispatcher(rootViewDispatcher, queueInfo.queueInstance.OnResume, true); // inlining allowed } } else { // Queue instance does exist. // Increment the count of root views. This is helpful for the case the count reaches 0 so we can cleanup the queue. queueInfo.rootViewCount++; } // Add tag _reactTagToOperationQueue.Add(tag, queueInfo.queueInstance); // Send forward queueInfo.queueInstance.AddRootView(tag, rootView, themedRootContext); }
/// <summary> /// Instantiates the <see cref="UIViewOperationQueue"/>. /// </summary> /// <param name="reactContext">The React context.</param> /// <param name="viewManagerRegistry"> /// The view manager registry. /// </param> public UIViewOperationQueue(ReactContext reactContext, ViewManagerRegistry viewManagerRegistry) { _reactContext = reactContext; _viewManagerRegistry = viewManagerRegistry; _active = false; // Corner case: UWP scenarios that start with no main window. // We create the UIViewOperationQueueInstance for main dispatcher thread ahead of time so animations // in secondary windows can work. var queueInfo = new QueueInstanceInfo() { queueInstance = new UIViewOperationQueueInstance( _reactContext, new NativeViewHierarchyManager(_viewManagerRegistry, DispatcherHelpers.MainDispatcher, OnViewsDropped), ReactChoreographer.Instance) }; _dispatcherToOperationQueueInfo.Add(DispatcherHelpers.MainDispatcher, queueInfo); _mainUiViewOperationsQueueInstance = queueInfo.queueInstance; }