flutter 当使用子ListView小部件时,GlobalKey会损坏,

ycggw6v2  于 6个月前  发布在  Flutter
关注(0)|答案(5)|浏览(77)

重现步骤

  1. 操作 按钮。
  2. 检查 _widgetKey.currentStateactionHandler 中。

预期结果

_widgetKey 应具有有效的 currentState , currentWidget

实际结果

_widgetKey 对于 currentStatecurrentWidget 和其他字段具有空值

代码示例

代码示例

import 'package:flutter/material.dart';

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

class MyPage extends StatefulWidget {
  const MyPage({super.key});

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

class MyPageState extends State<MyPage> {
  ListBody _widgets = const ListBody();
  final GlobalKey _widgetKey = GlobalKey();
  Widget inputWidget = const TextField();

  @override
  void initState() {
    setState(() {
      inputWidget = TextField(key: _widgetKey);
      _widgets = widgets(context);
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    var widget = Scaffold(
      body: ListView(
        children: [
          inputWidget,
          const Text("Widgets"),
          _widgets,
          TextButton(onPressed: actionHandler, child: const Text("Action")),
        ],
      ),
    );
    return widget;
  }

  void actionHandler() async {
    if (_widgetKey.currentState == null) {
      debugPrint("state is null");
    }
  }

  ListBody widgets(BuildContext context) {
    return ListBody(
        children: List.generate(18, (index) {
      return const TextField();
    }));
  }
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: const Center(child: MyPage()),
    );
  }
}

截图或视频

截图/视频演示
[上传媒体在这里]

日志

日志

[Paste your logs here]

Flutter Doctor 输出

Doctor 输出

flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 3.22.2, on Microsoft Windows [Version 10.0.22631.3880], locale uk-UA)
[√] Windows Version (Installed version of Windows is version 10 or higher)
[√] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
[√] Chrome - develop for the web
[√] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.8.3)
[√] Android Studio (version 2021.2)
[√] IntelliJ IDEA Community Edition (version 2023.1)
[√] VS Code (version 1.91.1)
[√] Connected device (3 available)
[√] Network resources

• No issues found!
mftmpeh8

mftmpeh81#

请注意,如果widgets方法生成的子部件少于18个,则一切正常。

cdmah0mi

cdmah0mi2#

感谢您的报告@pic16f887
您能检查https://stackoverflow.com/questions/75274817/global-key-is-not-restoring-state-sometimes-of-child-widget并看看它是否对您的情况有所帮助吗?

mrzz3bfm

mrzz3bfm3#

@darshankawar I am not sure that these issues are the same as I am passing _widgetKey to the TextField(key: _widgetKey) only once. And even when I pass key in build method the result is the same.
The problem is reproduced only when ListView contains less than some number of widgets (in my case if widgets generates more 18 widgets) everything works as expected. When I replacing ListView for SingleChildScrollView and Column as a Child the problem is gone.

5n0oy7gb

5n0oy7gb4#

感谢您的更新。我认为它在少于18个小部件的情况下可以正常工作,因为它可以渲染屏幕上的所有可用内容。对于18个,其中一些元素不在屏幕上,所以它们可能不会被计算。您可以尝试使用 ListView.builder 来通过索引获取项目,也可以尝试传递 reverse: true 来按需访问子项。

aiqt4smr

aiqt4smr5#

我认为在小于18个小部件的情况下,它可以正常工作,因为它可以渲染屏幕上的所有可用元素。对于18个,其中一些元素不在屏幕上,所以它们可能不会被计算。你可以尝试使用ListView.builder通过索引获取项目,也可以尝试传递reverse:true以按需访问子项。

@darshankawar 当我添加了除了inputWidgetText之外的17个小部件以及具有globalKeyinputWidgetText时,有些元素不在屏幕上,但我没有观察到这个问题。ListView.builder没有解决这个问题。

相关问题