Flame框架中HasGameReference与findGame()的区别是什么?
问题:HasGameReference 与 findGame() 的区别
我在Flame文档的示例代码中发现,StartPage使用HasGameReference来访问game属性,而PausePage同时使用了HasGameReference和findGame()函数。请问这两者之间有什么区别?
StartPage代码示例
class StartPage extends Component with HasGameReference<RouterGame> { 👈👈👈 StartPage() { addAll([ _logo = TextComponent( text: 'Your Game', textRenderer: TextPaint( style: const TextStyle( fontSize: 64, color: Color(0xFFC8FFF5), fontWeight: FontWeight.w800, ), ), anchor: Anchor.center, ), _button1 = RoundedButton( text: 'Level 1', action: () => game.router.pushNamed('level1'), 👈👈👈 color: const Color(0xffadde6c), borderColor: const Color(0xffedffab), ), ...
PausePage代码示例
class PausePage extends Component with TapCallbacks, HasGameReference<RouterGame> { 👈👈👈 @override Future<void> onLoad() async { final game = findGame()!; 👈👈👈 addAll([ ...
回答
1. 本质与使用方式
- HasGameReference:是Flame提供的mixin,混入后直接给Component注入一个类型化的
game成员变量,无需额外调用函数,直接通过game访问游戏实例。 - findGame():是Component类自带的方法,调用后会从当前组件向上遍历组件树,查找最近的Game实例,返回
Game?类型,需要自行处理空值。
2. 类型安全性
- HasGameReference:支持泛型指定(如
HasGameReference<RouterGame>),game属性是你指定的游戏类型,编译期就能保证类型安全,无需额外转换。 - findGame():默认返回
Game?,若需特定游戏类型,要手动做类型转换(如findGame() as RouterGame),存在运行时转换失败的风险。
3. 初始化时机
- HasGameReference的
game:在组件被挂载到游戏树(加入父组件或Game实例)时自动赋值。注意:若在组件构造函数中直接访问,可能未初始化,但示例中StartPage的game.router是在按钮回调中使用,此时组件已完成挂载,所以安全。 - findGame():只要组件已加入组件树,调用就能找到Game实例,即使在
onLoad生命周期中调用也能正常工作。
4. 依赖与灵活性
- HasGameReference:必须通过混入使用,代码耦合度稍高,但使用更便捷,适合长期需要访问Game实例的组件。
- findGame():无需任何混入,所有Component都可直接调用,灵活性更高,适合临时获取Game实例的场景。
关于示例中PausePage的冗余写法
示例里PausePage同时用HasGameReference和findGame()是没必要的——既然已经混入了mixin,直接用game属性即可,这种写法大概率是示例为了同时展示两种获取Game实例的方式。
内容的提问来源于stack exchange,提问作者shingo.nakanishi
相关产品推荐
相关产品推荐

