Appearance
MediaQuery对组件的影响
当虚拟键盘唤起时,Flutter会自动调用build
方法来重新构建UI,以适应键盘的变化。这是因为虚拟键盘的出现会改变屏幕的布局,需要更新UI以适应新的可见区域。 在键盘唤起时,MediaQuery.of(context)
的结果可能会发生变化,因为键盘占用了一部分屏幕空间。这会触发build
方法重新执行,并导致MediaQuery.of(context)
被再次调用。 如果你的代码中直接依赖于MediaQuery.of(context)
的结果,并且每次调用时都会触发build
方法的重新执行,那么会导致频繁的重建和重新渲染。这可能会对性能产生一定的影响,尤其是在构建复杂UI时。 避免直接使用MediaQuery.of(context).size
viewInsets
padding
viewPadding
为了避免频繁的重建,可以考虑在build
方法中将MediaQuery.of(context)
的结果缓存到局部变量中,并在需要使用时直接使用该变量。这样,即使触发了重建,只有在键盘状态发生改变的情况下会重新获取MediaQueryData
对象。
dart
Widget build(BuildContext context) {
final mediaQuery = MediaQuery.of(context);
// 在需要使用屏幕信息时,直接使用缓存的变量 mediaQuery
// ...
}
通过这种方式,可以减少不必要的MediaQuery.of(context)
调用,从而降低因虚拟键盘导致的重复构建对性能的影响。在键盘出现和隐藏的过程中,屏幕的可见区域会发生改变,如果你想要根据键盘的状态进行相应的布局调整,还是需要重新构建来更新UI。因此,不必过分担心键盘导致的重建,它是为了确保UI与键盘状态一致而必要的反应。
Scaffold 之外使用 MediaQuery.of(context)要谨慎
通过 Scaffold 内的 context 获取到的 MediaQueryData 将因为 Scaffold 重构被影响
dart
Scaffold(
resizeToAvoidBottomInset:true
)
如果为true,则[body]和脚手架的浮动小部件应自动调整大小,以避免因为环境MediaQuery
中MediaQueryData.viewInsets
底部属性定义的屏幕键盘出现时的高度变化重构。
在使用MediaQuery.of(context)
时,如果没有正确的上下文传递,可能会导致意想不到的结果。特别是在Scaffold之外使用MediaQuery.of(context)
时,需要谨慎处理。
在Flutter中,MediaQuery.of(context)
方法是通过上下文(BuildContext
)来访问屏幕信息的。上下文是一个包含了当前小部件树位置和配置信息的对象。但是,上下文的范围是有限的,它只在小部件树中有效。当我们在Scaffold之外使用MediaQuery.of(context)
时,可能会超出上下文的范围,导致无法获取正确的屏幕信息。
一个常见的示例是在应用程序的顶层MaterialApp
小部件的构建方法中使用MediaQuery.of(context)
。由于MaterialApp
是整个应用程序的根小部件,它还没有建立与具体UI对象的关联,所以此时使用MediaQuery.of(context)
将无法获取到正确的屏幕信息,可能会导致异常或错误的结果。
为了避免在Scaffold之外使用MediaQuery.of(context)
时出现问题,可以考虑以下方法:
- 将需要访问屏幕信息的代码放在Scaffold内部,这样可以确保在正确的上下文范围内获取屏幕信息。
- 使用
Builder
小部件将代码包裹起来,以确保在正确的上下文范围内获取屏幕信息。Builder
小部件会提供一个新的上下文,以便在内部使用MediaQuery.of(context)
。
dart
Widget build(BuildContext context) {
return Scaffold(
body: Builder(
builder: (BuildContext context) {
// 在Builder内部使用 MediaQuery.of(context)
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
// ...
);
},
),
);
}
替代
有时候,你需要使用MediaQuery.of(context)来获取屏幕信息,但是由于上下文范围问题,导致无法获取正确的屏幕信息。这时,你可以考虑使用其他方法来获取屏幕信息。 比如在组件中使用double.infinity来获取屏幕宽度,或者使用LayoutBuilder来获取屏幕信息。