Closed pic16f887 closed 4 weeks ago
It's important to note if widgets
method generates less than 18 children widgets then everything works as expected.
Thanks for the report @pic16f887 Can you check https://stackoverflow.com/questions/75274817/global-key-is-not-restoring-state-sometimes-of-child-widget and see if it helps in your case or not ?
@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.
Thanks for the update. I think it works with less than 18 widgets because it can render all that are available on screen. For 18, some of the elements are off-the screen so they may not be counted. Can you try with ListView.builder
to get the items by their index, you can also try to pass reverse: true
to access children on demand.
I think it works with less than 18 widgets because it can render all that are available on screen. For 18, some of the elements are off-the screen so they may not be counted. Can you try with ListView.builder to get the items by their index, you can also try to pass reverse: true to access children on demand.
@darshankawar When I add 17 widgets in addition to the inputWidget
and Text
that has globalKey
, some elements are off the screen but I don't observe this issue. ListView.builder doesn't solve the issue.
Thanks for the update. I am not sure if this is a bug or not. With 18 elements, it prints:
I/flutter (23250): state is null
With less than 18, it does not. Will keep the issue open for team's tracking.
Is the widget that has the global key actually visible on screen? The ListView builds its children lazily. If the widget is not on screen, it is not included in the tree and hence not connected to the global key.
@goderbauer Yes, it's visible on the screen when I read the state. In my application it's added dynamically so I have added a similar logic to the example. Even with this code the issue is reproduced
@override
Widget build(BuildContext context) {
var widget = Scaffold(
body: ListView(
children: [
TextField(key: _widgetKey), // inputWidget is replaced with TextField(key: _widgetKey)
const Text("Widgets"),
_widgets,
TextButton(onPressed: actionHandler, child: const Text("Action")),
],
),
);
return widget;
}
@pic16f887 can you share the device you are experiencing this on? I have not been able to reproduce the issue.
@Piinks I have this issue on Windows 11.
Thanks for letting us know!
I have tried it, and it looks like it only happens when the widget in question is scrolled off screen. This is expected, since it being off screen means it will be disposed.
The API docs discusses ways to modify this behavior, see under the heading Destruction mitigation
: https://api.flutter.dev/flutter/widgets/ListView-class.html
There is also some sample code here: https://api.flutter.dev/flutter/widgets/ListView/ListView.custom.html#widgets.ListView.custom.1
@Piinks Thank you for the information about Destruction mitigation. I have modified my example and added AutomaticKeepAliveClientMixin
to MyPageState
but I still unable to get state from _widgetKey
when ListBody
generates 18 or more widgets.
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> with AutomaticKeepAliveClientMixin {
final ListBody _widgets = ListBody(
children: List.generate(18, (index) {
return const TextField();
}));
final GlobalKey _widgetKey = GlobalKey();
Widget inputWidget = const TextField();
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
super.build(context);
return Scaffold(
body: ListView(
children: [
TextField(key: _widgetKey),
const Text("Widgets"),
_widgets,
TextButton(onPressed: actionHandler, child: const Text("Action")),
],
),
);
}
void actionHandler() async {
if (_widgetKey.currentState == null) {
debugPrint("state is null");
}
}
}
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()),
);
}
}
The keep alive should be applied to the children of the list view. Not the list itself.
Without additional information, we are unfortunately not sure how to resolve this issue. We are therefore reluctantly going to close this bug for now. If you find this problem please file a new issue with the same description, what happens, logs and the output of 'flutter doctor -v'. All system setups can be slightly different so it's always better to open new issues and reference the related ones. Thanks for your contribution.
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v
and a minimal reproduction of the issue.
Steps to reproduce
_widgetKey.currentState
inactionHandler
.Expected results
_widgetKey
should have validcurrentState
,currentWidget
valuesActual results
_widgetKey
has null values forcurrentState
,currentWidget
and other fieldsCode sample
Code sample
```dart 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 StateScreenshots or Video
Screenshots / Video demonstration
[Upload media here]Logs
Logs
```console [Paste your logs here] ```Flutter Doctor output
Doctor output
```console 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! ```