Skip to content

(Insert|Move|Remove)ChildRenderObject methods lack parity #63269

Closed

Description

@tvolkert

Problem Statement

Currently, these methods have the following signatures:

void insertChildRenderObject(covariant RenderObject child, covariant dynamic slot);
void moveChildRenderObject(covariant RenderObject child, covariant dynamic slot);
void removeChildRenderObject(covariant RenderObject child);

Not having the old slot in the cases of move and remove makes it difficult for render objects to efficiently locate the child in question without having to scan for it in order to move or remove it. This in turn has yielded a code smell of the childToSlot mapping pattern that has been copied in several places in the framework:

final Map<Element, _CupertinoTextSelectionToolbarItemsSlot> childToSlot = <Element, _CupertinoTextSelectionToolbarItemsSlot>{};

final Map<Element, _ChipSlot> childToSlot = <Element, _ChipSlot>{};

final Map<RenderBox, _DecorationSlot> childToSlot = <RenderBox, _DecorationSlot>{};

final Map<Element, _ListTileSlot> childToSlot = <Element, _ListTileSlot>{};

Alternative

Since render objects have various different child models (single child list, multiple child lists, named children), it would be very useful if the signatures were as follows:

void insertChildRenderObject(covariant RenderObject child, covariant dynamic slot);
void moveChildRenderObject(covariant RenderObject child, covariant dynamic oldSlot, covariant dynamic newSlot);
void removeChildRenderObject(covariant RenderObject child, covariant dynamic slot);

The difference is the addition of the old slot for move and remove. Passing this information would allow the render object to efficiently locate the child in question without having to scan for it in order to move or remove it.

Breaking Change Mitigation

The proposed API above has the problem that it's a hard breaking change for any code that extends RenderObjectElement -- so basically any custom render objects. That's a big enough breaking change that it's basically a non-starter as written above.

So I propose that we transition to new API methods with the desired signature -- with a soft transition and deprecation period.

// The new methods, eventually to be made abstract, are initially (during the soft
// transition period) stub impls that just delegate to the deprecated methods.

@protected
void insertRenderObjectChild(covariant RenderObject child, covariant dynamic slot) {
  insertChildRenderObject(child, slot);
}

@protected
void moveRenderObjectChild(covariant RenderObject child, covariant dynamic oldSlot, covariant dynamic newSlot) {
  moveChildRenderObject(child, newSlot);
}

@protected
void removeRenderObjectChild(covariant RenderObject child, covariant dynamic slot) {
  removeChildRenderObject(child);
}

// The deprecated methods cease to be abstract, and instead provide stub impls
// that throw, pointing the user to implement the new signatures.

@Deprecated('Override insertRenderObjectChild instead')
void insertChildRenderObject(covariant RenderObject child, covariant dynamic slot) {
  assert(() {
    // Throw an error instructing them to implement insertRenderObjectChild()
  }());
}

@Deprecated('Override moveRenderObjectChild instead')
void moveChildRenderObject(covariant RenderObject child, covariant dynamic slot) {
  assert(() {
    // Throw an error instructing them to implement moveRenderObjectChild()
  }());
}

@Deprecated('Override removeRenderObjectChild instead')
void removeChildRenderObject(covariant RenderObject child) {
  assert(() {
    // Throw an error instructing them to implement removeRenderObjectChild()
  }());
}

Other Info

It's worth noting that the framework has this extra slot information in hand - wiring it up would be trivial:

_ancestorRenderObjectElement.moveChildRenderObject(renderObject, slot);

_ancestorRenderObjectElement.removeChildRenderObject(renderObject);

Activity

  1. added
    frameworkflutter/packages/flutter repository. See also f: labels.
    c: API breakBackwards-incompatible API changes
    a: qualityA truly polished experience
    P2Important issues not at the top of the work list
    on Aug 8, 2020
  2. tvolkert commented on Aug 8, 2020

    @tvolkert
    ContributorAuthor

    This will require dart-lang/sdk#42991

  3. Hixie commented on Aug 8, 2020

    @Hixie
    Contributor

    SGTM. Make it so.

    We could use @mustCallSuper instead of (as well as) @deprecated, so we wouldn't need to wait until dart-lang/sdk#42991.

    cc @goderbauer

  4. added
    perf: app sizePerformance issues related to app size (binary/code size) or disk space
    perf: memoryPerformance issues related to memory
    perf: speedPerformance issues related to (mostly rendering) speed
    c: performanceRelates to speed or footprint issues (see "perf:" labels)
    on Aug 8, 2020
  5. goderbauer commented on Aug 10, 2020

    @goderbauer
    Member

    SGTM as well.

  6. self-assigned this
    on Aug 19, 2020
  7. tvolkert commented on Aug 21, 2020

    @tvolkert
    ContributorAuthor

    The initial part of this is done now. All that's left to do is to remove the deprecated methods after the change has been in stable. I'm closing this, since there's no need to leave the issue open to track the final removal/cleanup

  8. github-actions commented on Aug 13, 2021

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  9. locked as resolved and limited conversation to collaborators on Aug 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work lista: qualityA truly polished experiencec: API breakBackwards-incompatible API changesc: performanceRelates to speed or footprint issues (see "perf:" labels)frameworkflutter/packages/flutter repository. See also f: labels.perf: app sizePerformance issues related to app size (binary/code size) or disk spaceperf: memoryPerformance issues related to memoryperf: speedPerformance issues related to (mostly rendering) speed

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions