MouseTracker 不再附加注释
概述
MouseTracker
的方法 attachAnnotation
、detachAnnotation
和 isAnnotationAttached
已被移除。
上下文
在渲染阶段,通过在感兴趣区域上放置 MouseTrackerAnnotation
可以检测鼠标事件,例如鼠标指针进入、退出或悬停在区域上。每次更新(一个新的帧或事件)时,
MouseTracker
会比较更新前后鼠标指针悬停的注释,然后执行相应的回调。
MouseTracker
类管理鼠标指针的状态,要求 MouseRegion
在挂载(mounted)时附加注释,在移除(unmounted)时分离注释。MouseTracker
使用它来执行 挂载退出检查。(例如,如果是因移除 widget 引起的退出,则不调用 MouseRegion.onExit
),防止移除 widget 时调用 setState
引发的异常(详情可见 Issue #44631)。
这种机制已经被 MouseRegion
变为一个有状态的 widget 所取代,它可以通过在卸载时阻止回调来自行执行挂载退出检查。因此,这些方法已被删除,MouseTracker
不再跟踪屏幕上的所有注释。
更改描述
MouseTracker
类删除了三个与附加注释相关的方法:
class MouseTracker extends ChangeNotifier {
// ...
- void attachAnnotation(MouseTrackerAnnotation annotation) {/* ... */}
- void detachAnnotation(MouseTrackerAnnotation annotation) {/* ... */}
- @visibleForTesting
- bool isAnnotationAttached(MouseTrackerAnnotation annotation) {/* ... */}
}
RenderMouseRegion
和 MouseTrackerAnnotation
不再执行挂载退出检查,在 MouseRegion
中仍然执行。
迁移指南
删除 MouseTracker.attachAnnotation
和 detachAnnotation
的调用,这几乎没有影响:
-
MouseRegion
的使用应该完全不受影响。 -
如果你的代码直接使用
RenderMouseRegion
或MouseTrackerAnnotation
,请注意现在onExit
的回调会在MouseTracker.detachAnnotation
事件引起的退出时触发。如果不涉及任何状态,应该不会有问题,否则你可能希望添加挂载的退出检查,尤其是在回调泄漏时,以便外部 widget 可以调用setState
。例如:
迁移前的代码:
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); };
}
}
迁移后的代码:
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 : (_) {};
}
}
必须删除 MouseTracker.isAnnotationAttached
的调用。由于注释不再被跟踪,因此该功能在技术上不再可行。如果你需要此功能,请提交 issue。
时间轴
发布于版本:1.15.4
发布于稳定版本:1.17
参考文献
API 文档:
相关 PR:
- 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.