【发布时间】:2022-11-24 18:17:07
【问题描述】:
我的小部件多次运行其 FutureBuilder 代码时遇到问题,Future 已解决。与 SO 上关于此的其他问题不同,我的 build() 方法没有被多次调用。
我的未来在build()之外被initState()调用 - 它也被包裹在AsyncMemoizer中。
相关代码:
class _HomeScreenState extends State<HomeScreen> {
late final Future myFuture;
final AsyncMemoizer _memoizer = AsyncMemoizer();
@override
void initState() {
super.initState();
/// provider package
final homeService = context.read<HomeService>();
myFuture = _memoizer.runOnce(homeService.getMyData);
}
@override
Widget build(BuildContext context) {
print("[HOME] BUILDING OUR HOME SCREEN");
return FutureBuilder(
future: myFuture,
builder: ((context, snapshot) {
print("[HOME] BUILDER CALLED WITH SNAPSHOT: $snapshot - connection state: ${snapshot.connectionState}");
当我运行代码并触发错误时(显示的软键盘设法在 50% 的时间内触发它,但并非所有时间),我的日志是:
I/flutter (29283): [HOME] BUILDING OUR HOME SCREEN
I/flutter (29283): [HOME] BUILDER CALLED WITH SNAPSHOT: AsyncSnapshot<dynamic>(ConnectionState.waiting, null, null, null) - connection state: ConnectionState.waiting
I/flutter (29283): [HOME] BUILDER CALLED WITH SNAPSHOT: AsyncSnapshot<dynamic>(ConnectionState.done, Instance of 'HomeData', null, null) - connection state: ConnectionState.done
...
/// bug triggered
...
I/flutter (29283): [HOME] BUILDER CALLED WITH SNAPSHOT: AsyncSnapshot<dynamic>(ConnectionState.done, Instance of 'HomeData', null, null) - connection state: ConnectionState.done
ConnectionState.waiting 的初始调用是正常的,然后我们使用ConnectionState.done 获得第一个构建。
触发错误后,我得到了另一个FutureBuilder resolve没有build() 方法被调用。
我在这里错过了什么吗?
用完整的例子编辑
这显示了有问题的错误 - 如果您单击进入和退出 TextField,将再次调用 FutureBuilder。
这似乎与键盘的隐藏方式有关。如果我使用FocusScopeNode方法,它会重建,而如果我使用FocusManager,它不会,所以我不确定这是否是一个错误。
import 'package:flutter/material.dart';
void main() async {
runApp(const TestApp());
}
class TestApp extends StatelessWidget {
const TestApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Testapp',
home: Scaffold(
body: TestAppHomeScreen(),
),
);
}
}
class TestAppHomeScreen extends StatefulWidget {
const TestAppHomeScreen({super.key});
@override
State<TestAppHomeScreen> createState() => _TestAppHomeScreenState();
}
class _TestAppHomeScreenState extends State<TestAppHomeScreen> {
late final Future myFuture;
@override
void initState() {
super.initState();
myFuture = Future.delayed(const Duration(milliseconds: 500), () => true);
print("[HOME] HOME SCREEN INIT STATE CALLED: $hashCode");
}
@override
Widget build(BuildContext context) {
print("[HOME] HOME SCREEN BUILD CALLED: $hashCode");
return FutureBuilder(
future: myFuture,
builder: (context, snapshot) {
print("[HOME] HOME SCREEN FUTURE BUILDER CALLED WITH STATE ${snapshot.connectionState}: $hashCode");
if (snapshot.connectionState == ConnectionState.waiting) {
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
return GestureDetector(
onTapUp: (details) {
// hide the keyboard if it's showing
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
// FocusManager.instance.primaryFocus?.unfocus();
},
child: const Scaffold(
body: Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 32.0),
child: TextField(),
),
),
),
);
},
);
}
}
【问题讨论】:
-
我无法重现这个,你能更具体地说明你所指的这个“错误”吗?你能发布一个完整的可重现的例子吗?
-
我添加了一个可重现的例子@venir
标签: flutter