MouseTracker 不再附加注释
概述
#移除了 MouseTracker
的方法 attachAnnotation
、detachAnnotation
和 isAnnotationAttached
。
背景
#鼠标事件,例如鼠标指针进入、离开或悬停在某个区域时,是借助在渲染阶段放置在相关区域的 MouseTrackerAnnotation
来检测的。每次更新(新帧或新事件)时,MouseTracker
会比较更新前后鼠标指针悬停的注释,然后相应地分派回调。
管理鼠标指针状态的 MouseTracker
类,曾经要求 MouseRegion
在挂载时附加注释,并在卸载时分离注释。MouseTracker
使用此机制来执行*挂载退出检查*(例如,如果退出是由组件卸载引起的,则不得调用 MouseRegion.onExit
),以防止调用未挂载组件的 setState
并抛出异常(详见问题 #44631)。
此机制已被替换为将 MouseRegion
变为一个有状态组件,以便它可以在卸载时通过阻塞回调来自行执行挂载退出检查。因此,这些方法已被移除,并且 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
,请注意,当退出是由以前调用MouseTracker.detachAnnotation
的事件引起时,现在会调用onExit
。如果没有涉及状态,这应该不是问题;否则,您可能需要添加挂载退出检查,特别是如果回调泄露导致外部组件可能在其内部调用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
的调用。此功能在技术上已不再可能,因为注释不再被跟踪。如果您仍需要此功能,请提交问题。
时间线
#引入版本: 1.15.4
稳定版本: 1.17
参考资料
#API 文档
相关 PR
- MouseTracker 不再需要附加注释,这带来了这项变更。
- 改进 MouseTracker 生命周期:将检查移至后帧,这首次引入了挂载退出变更,并在onExit 的变更中进行了详细解释。