sendSemanticsUpdate method Null safety

void sendSemanticsUpdate()

Update the semantics using dart:ui.PlatformDispatcher.updateSemantics.

Implementation

void sendSemanticsUpdate() {
  if (_dirtyNodes.isEmpty) {
    return;
  }
  final Set<int> customSemanticsActionIds = <int>{};
  final List<SemanticsNode> visitedNodes = <SemanticsNode>[];
  while (_dirtyNodes.isNotEmpty) {
    final List<SemanticsNode> localDirtyNodes = _dirtyNodes.where((SemanticsNode node) => !_detachedNodes.contains(node)).toList();
    _dirtyNodes.clear();
    _detachedNodes.clear();
    localDirtyNodes.sort((SemanticsNode a, SemanticsNode b) => a.depth - b.depth);
    visitedNodes.addAll(localDirtyNodes);
    for (final SemanticsNode node in localDirtyNodes) {
      assert(node._dirty);
      assert(node.parent == null || !node.parent!.isPartOfNodeMerging || node.isMergedIntoParent);
      if (node.isPartOfNodeMerging) {
        assert(node.mergeAllDescendantsIntoThisNode || node.parent != null);
        // if we're merged into our parent, make sure our parent is added to the dirty list
        if (node.parent != null && node.parent!.isPartOfNodeMerging) {
          node.parent!._markDirty(); // this can add the node to the dirty list
          node._dirty = false; // We don't want to send update for this node.
        }
      }
    }
  }
  visitedNodes.sort((SemanticsNode a, SemanticsNode b) => a.depth - b.depth);
  final ui.SemanticsUpdateBuilder builder = SemanticsBinding.instance.createSemanticsUpdateBuilder();
  for (final SemanticsNode node in visitedNodes) {
    assert(node.parent?._dirty != true); // could be null (no parent) or false (not dirty)
    // The _serialize() method marks the node as not dirty, and
    // recurses through the tree to do a deep serialization of all
    // contiguous dirty nodes. This means that when we return here,
    // it's quite possible that subsequent nodes are no longer
    // dirty. We skip these here.
    // We also skip any nodes that were reset and subsequently
    // dropped entirely (RenderObject.markNeedsSemanticsUpdate()
    // calls reset() on its SemanticsNode if onlyChanges isn't set,
    // which happens e.g. when the node is no longer contributing
    // semantics).
    if (node._dirty && node.attached) {
      node._addToUpdate(builder, customSemanticsActionIds);
    }
  }
  _dirtyNodes.clear();
  for (final int actionId in customSemanticsActionIds) {
    final CustomSemanticsAction action = CustomSemanticsAction.getAction(actionId)!;
    builder.updateCustomAction(id: actionId, label: action.label, hint: action.hint, overrideId: action.action?.index ?? -1);
  }
  SemanticsBinding.instance.platformDispatcher.updateSemantics(builder.build());
  notifyListeners();
}