文章目录
- 1. 问题描述
- 2. 优化方法
- 2.1 缩小范围
- 2.2 替代方法
- 3. 示例代码
- 4. 内容总结
我们在上一章回中介绍了"如何获取AppBar的高度"相关的内容,本章回中将介绍关于MediaQuery的优化.闲话休提,让我们一起Talk Flutter吧。
1. 问题描述
我们在前面章回中介绍获取屏幕参数时使用过MediaQuery类,主要通过它来获取MediaQueryData对象,然后从MediaQueryData对象中获取屏幕相关的参数。比如
常用的屏幕长度和宽度,不过在使用时如果遇到键盘弹出或者隐藏时会引起Scaffold进行重绘(rebuild),而且是多次重绘,这种重绘显然不合理,它会导致不必要的
性能开销,本章回中将介绍如何优化这种不合理的重绘。
2. 优化方法
明白我们遇到的问题后,我们介绍如何去解决这个问题,我们提供了两种解决方法,在接下来的小节中将介绍这两种方法。
2.1 缩小范围
我可以在使用MediaQuery的地方嵌套一个Build组件,这样可以让重绘只发生在Build组件内部,进而不影响页面中其它的组件。这种做法相当是缩小了重绘范围。
2.2 替代方法
我们还可以使用MediaQuery.sizeof()代替原来的方法,不过这种办法有一定的局限性,比如viewInsetOf方法就没有效果。它仍然会进行重绘。我推测它需要计算
键盘高度,因此才去重绘。不过只是推测而已,真实的原因还需要查看源代码后才能明白。
3. 示例代码
Widget build(BuildContext context) {
// double screenWidth = MediaQuery.of(context).size.width;
// double screenHeight = MediaQuery.of(context).size.height;
///使用下面的方法代替上面的方法,可以减少页面重绘
double screenWidth = MediaQuery.sizeOf(context).width;
double screenHeight = MediaQuery.sizeOf(context).height;
debugPrint("build running");
///键盘高度,没有键盘弹出时为0
// debugPrint("keyboard 1: ${MediaQuery.of(context).viewInsets.bottom}");
///这个方法不会减少页面重绘,可见只对sizeof有效果。
// debugPrint("keyboard 1: ${MediaQuery.viewInsetsOf(context).bottom}");
///底部安全区域高度,没有时为0
// debugPrint("keyboard 2: ${MediaQuery.of(context).viewPadding.bottom}");
///没有实际意义
// debugPrint("keyboard 3: ${MediaQuery.of(context).viewInsets.top}");
///顶部状态栏的高度
// debugPrint("keyboard 4: ${MediaQuery.of(context).viewPadding.top}");
return Scaffold(
appBar: AppBar(
title: const Text("Example of Scaffold Overlay"),
),
body: Stack(
children: [
Positioned(
top: 400,
left: 0,
///嵌套一层builder就不会引起页面重绘
child: Builder(builder: (context) {
double y = MediaQuery.of(context).size.height;
debugPrint("build running of builder");
return Text("check rebuilding value: ${y.toString()}");
}),
),
///键盘自动弹出时会导到MediaQuery进行页面重绘,有两种解决方法:更换接口,嵌套builder
const Positioned(
top: 450,
left: 0,
width: 300,
height: 56,
child: TextField(),
),
],
),
);
}
上面的示例代码中大量使用了MediaQuery类,在页面中包含一个输入框,当我们点击输入框时会自动弹出键盘,此时可以看到代码中添加的日志出现在了运行结果中,
这表明页面发生了生绘,具体点讲就是build方法在运行,而且会运行多次,输入完成后,点击键盘上的确认键,键盘会自动隐藏,此时也会发生重绘。我们使用上一小
节介绍的两种优化方法后,再次在输入框中输入内容,此时,页面不会发生重绘。我在这里就不演示具体的运行结果了,建议大家自己动手去实践。
4. 内容总结
最后,我们对本章回的内容做一个全面的总结:
- 页面中使用MediaQuery类后,当键盘自动弹出和隐藏时会引起页面重绘;
- 使用Build组件来缩小重绘范围,这样可以避免页面发生重绘;
- 使用MediaQuery中的其它方法可以避免重绘,不过不是所有方法都有效果;
看官们,与"关于MediaQuery的优化"相关的内容就介绍到这里,欢迎大家在评论区交流与讨论!