dart 在构建函数中声明MediaQuery时的重建问题

omqzjyyz  于 9个月前  发布在  其他
关注(0)|答案(3)|浏览(65)
import 'package:bug_fix/home_screen.dart';
import 'package:flutter/material.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

@OverRide
Widget build(BuildContext context) {
return const MaterialApp(
home: HomeScreen(),
);
}
}

import 'dart:developer';
import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});

@OverRide
Widget build(BuildContext context) {
log('Building home screen');
// Variable to find the size of the device screen.
final Size size = MediaQuery.of(context).size;
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(),
],
),
);
}
}

1.创建一个普通的无状态小部件。
1.在build函数中编写MediaQuery。

  1. MediaQuery是final Size size = MediaQuery.of(context).size;
    1.在构建函数日志中写入日志(“Build function called”);.
    1.在Scaffold的主体上写一列。
    1.将mainAxisAlignment设置为中心。
    1.创建一个textformfiled。
    1.打开/聚焦textformfiled,然后构建函数将重建多次。
    我明白这是因为,当我打开textformfiled时,设备屏幕的大小发生了变化。
ipakzgxi

ipakzgxi1#

从Flutter 3.10及以上版本,
替换:

final size = MediaQuery.of(context).size;

final size = MediaQuery.SizeOf(context);

通过调用MediaQuery.of(context).size,小部件将在任何MediaQuery属性更改时重新构建(性能降低)。通过调用MediaQuery.sizeOf(context),小部件将仅在属性更改时重新构建,从而避免不必要的重新构建。
要了解更多信息,请参阅issue,其中有很好的解释。

pxq42qpu

pxq42qpu2#

您遇到的问题是,当您打开/聚焦TextFormField时,您的小部件的构建函数被多次调用,这是Flutter中的预期行为。每当需要重新构建小部件时,就会调用build方法,这可能是由于各种原因造成的,包括小部件状态的更改或小部件树的更改。
在您的情况下,当您打开/聚焦TextFormField时,它可能会触发其父小部件的重建,因为显示键盘时设备屏幕的大小可能会更改。这就是为什么您会多次看到“Building home screen”日志消息的原因。
如果希望避免不必要地重新构建HomeScreen小部件,可以考虑使用StatefulWidget并管理小部件的状态。通过这样做,您可以控制何时应该进行重建。
下面是一个可能的解决方案:

import 'dart:developer';
import 'package:flutter/material.dart';

class HomeScreen extends StatefulWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  @override
  Widget build(BuildContext context) {
    log('Building home screen');
    final Size size = MediaQuery.of(context).size;

    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          TextFormField(),
        ],
      ),
    );
  }
}

通过使用StatefulWidget,构建方法将仅在显式调用setState时被调用,从而允许您控制何时需要重新构建小部件。

ecr0jaav

ecr0jaav3#

有几个问题需要解决:

  1. @OverRide注解不正确。它们应该是@override(带小写“o”)。调试时应该显示错误吗???
    1.构造函数参数中的super.key是不需要的。你可以移除它。
  2. MyApp类构造函数中有一个typo。而不是const MyApp({super.key});,应该是const MyApp({Key? key}) : super(key: key);

相关问题