void markNeedsSemanticsUpdate({bool onlyChanges: false, bool noGeometry: false })

Mark this node as needing an update to its semantics description.

If the change did not involve a removal or addition of semantics, only the change of semantics (e.g. isChecked changing from true to false, as opposed to isChecked changing from being true to not being changed at all), then you can pass the onlyChanges argument with the value true to reduce the cost. If semantics are being added or removed, more work needs to be done to update the semantics tree. If you pass 'onlyChanges: true' but this node, which previously had a SemanticsNode, no longer has one, or previously did not set any semantics, but now does, or previously had a child that returned annotators, but no longer does, or other such combinations, then you will either assert during the subsequent call to PipelineOwner.flushSemantics() or you will have out-of-date information in the semantics tree.

If the geometry might have changed in any way, then again, more work needs to be done to update the semantics tree (to deal with clips). You can pass the noGeometry argument to avoid this work in the case where only the labels or flags changed. If you pass 'noGeometry: true' when the geometry did change, the semantic tree will be out of date.

Source

void markNeedsSemanticsUpdate({ bool onlyChanges: false, bool noGeometry: false }) {
  assert(!attached || !owner._debugDoingSemantics);
  if ((attached && owner._semanticsOwner == null) || (_needsSemanticsUpdate && onlyChanges && (_needsSemanticsGeometryUpdate || noGeometry)))
    return;
  if (!noGeometry && (_semantics == null || (_semantics.hasChildren && _semantics.wasAffectedByClip))) {
    // Since the geometry might have changed, we need to make sure to reapply any clips.
    _needsSemanticsGeometryUpdate = true;
  }
  if (onlyChanges) {
    // The shape of the tree didn't change, but the details did.
    // If we have our own SemanticsNode (our _semantics isn't null)
    // then mark ourselves dirty. If we don't then we are using an
    // ancestor's; mark all the nodes up to that one dirty.
    RenderObject node = this;
    while (node._semantics == null && node.parent is RenderObject) {
      if (node._needsSemanticsUpdate)
        return;
      node._needsSemanticsUpdate = true;
      node = node.parent;
    }
    if (!node._needsSemanticsUpdate) {
      node._needsSemanticsUpdate = true;
      if (owner != null)
        owner._nodesNeedingSemantics.add(node);
    }
  } else {
    // The shape of the semantics tree around us may have changed.
    // The worst case is that we may have removed a branch of the
    // semantics tree, because when that happens we have to go up
    // and dirty the nearest _semantics-laden ancestor of the
    // affected node to rebuild the tree.
    RenderObject node = this;
    do {
      if (node.parent is! RenderObject)
        break;
      node._needsSemanticsUpdate = true;
      node._semantics?.reset();
      node = node.parent;
    } while (node._semantics == null);
    node._semantics?.reset();
    if (!node._needsSemanticsUpdate) {
      node._needsSemanticsUpdate = true;
      if (owner != null)
        owner._nodesNeedingSemantics.add(node);
    }
  }
}