MouseTracker no longer attaches annotations
Summary
#Removed MouseTracker
's methods attachAnnotation
,
detachAnnotation
, and isAnnotationAttached
.
Context
#Mouse events, such as when a mouse pointer has entered a region,
exited, or is hovering over a region, are detected with the help of
MouseTrackerAnnotation
s that are placed on interested regions
during the render phase. Upon each update (a new frame or a new event),
MouseTracker
compares the annotations hovered by the mouse
pointer before and after the update, then dispatches
callbacks accordingly.
The MouseTracker
class, which manages the state of mouse pointers,
used to require MouseRegion
to attach annotations when mounted,
and detach annotations when unmounted.
This was used by MouseTracker
to perform the
mounted-exit check (for example, MouseRegion.onExit
must not be called if the exit was caused by the unmounting
of the widget), in order to prevent calling setState
of an unmounted widget and throwing exceptions (explained
in detail in Issue #44631).
This mechanism has been replaced by making MouseRegion
a stateful widget, so that it can perform the mounted-exit
check by itself by blocking the callback when unmounted.
Therefore, these methods have been removed, and MouseTracker
no longer tracks all annotations on the screen.
Description of change
#The MouseTracker
class has removed three methods related
to attaching annotations:
class MouseTracker extends ChangeNotifier {
// ...
void attachAnnotation(MouseTrackerAnnotation annotation) {/* ... */}
void detachAnnotation(MouseTrackerAnnotation annotation) {/* ... */}
@visibleForTesting
bool isAnnotationAttached(MouseTrackerAnnotation annotation) {/* ... */}
}
RenderMouseRegion
and MouseTrackerAnnotation
no longer perform the
mounted-exit check, while MouseRegion
still does.
Migration guide
#Calls to MouseTracker.attachAnnotation
and
detachAnnotation
should be removed with little to no impact:
- Uses of
MouseRegion
should not be affected at all. - If your code directly uses
RenderMouseRegion
orMouseTrackerAnnotation
, be aware thatonExit
is now called when the exit is caused by events that used to callMouseTracker.detachAnnotation
. This should not be a problem if no states are involved, otherwise you might want to add the mounted-exit check, especially if the callback is leaked so that outer widgets might callsetState
in it. For example:
Code before migration:
class MyMouseRegion extends SingleChildRenderObjectWidget {
const MyMouseRegion({this.onHoverChange});
final ValueChanged<bool> onHoverChange;
@override
RenderMouseRegion createRenderObject(BuildContext context) {
return RenderMouseRegion(
onEnter: (_) { onHoverChange(true); },
onExit: (_) { onHoverChange(false); },
);
}
@override
void updateRenderObject(BuildContext context, RenderMouseRegion renderObject) {
renderObject
..onEnter = (_) { onHoverChange(true); }
..onExit = (_) { onHoverChange(false); };
}
}
Code after migration:
class MyMouseRegion extends SingleChildRenderObjectWidget {
const MyMouseRegion({this.onHoverChange});
final ValueChanged<bool> onHoverChange;
@override
RenderMouseRegion createRenderObject(BuildContext context) {
return RenderMouseRegion(
onEnter: (_) { onHoverChange(true); },
onExit: (_) { onHoverChange(false); },
);
}
@override
void updateRenderObject(BuildContext context, RenderMouseRegion renderObject) {
renderObject
..onEnter = (_) { onHoverChange(true); }
..onExit = (_) { onHoverChange(false); };
}
@override
void didUnmountRenderObject(RenderMouseRegion renderObject) {
renderObject
..onExit = onHoverChange == null ? null : (_) {};
}
}
Calls to MouseTracker.isAnnotationAttached
must be removed.
This feature is no longer technically possible,
since annotations are no longer tracked.
If you somehow need this feature, please submit an issue.
Timeline
#Landed in version: 1.15.4
In stable release: 1.17
References
#API documentation:
Relevant PRs:
- MouseTracker no longer requires annotations attached, which made the change
- Improve MouseTracker lifecycle: Move checks to post-frame, which first introduced the mounted-exit change, explained at The change to onExit.
除非另有说明,本文档之所提及适用于 Flutter 的最新稳定版本,本页面最后更新时间: 2024-08-16。 查看文档源码 或者 为本页面内容提出建议。