gpt4 book ai didi

layout - 当 FutureBuilder 在 LayoutBuilder 中时 flutter 无限循环

转载 作者:IT王子 更新时间:2023-10-29 07:09:08 28 4
gpt4 key购买 nike

我在 LayoutBuilder 中有一个 PageView 来获取小部件的大小。由于它取决于小部件的大小,因此在构建小部件之前我不知道会有多少页面。所以我在LayoutBuilder里面加了FutureBuilder,这样就可以异步计算页数了。这是我的代码,但它在 ConnectionState.waiting 中无限期等待。代码中有什么问题,如何解决?

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(home: ScrollableTabsDemo());
}
}

class _Page {
const _Page({this.icon, this.text});
final IconData icon;
final String text;
}

const List<_Page> _allPages = <_Page>[
_Page(text: 'tab 1'),
_Page(text: 'tab 2'),
_Page(text: 'tab 3'),
];

class ScrollableTabsDemo extends StatefulWidget {
static const String routeName = '/material/scrollable-tabs';

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

class ScrollableTabsDemoState extends State<ScrollableTabsDemo>
with SingleTickerProviderStateMixin {
TabController _controller;

@override
void initState() {
super.initState();
_controller = TabController(vsync: this, length: _allPages.length);
}

@override
void dispose() {
_controller.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
final Color iconColor = Theme.of(context).accentColor;
return Scaffold(
appBar: AppBar(
title: const Text('Scrollable tabs'),
bottom: TabBar(
controller: _controller,
isScrollable: true,
tabs: _allPages.map<Tab>((_Page page) {
return Tab(text: page.text);
}).toList(),
),
),
body: TabBarView(
controller: _controller,
children: _allPages.map<Widget>((_Page page) {
return SafeArea(
top: false,
bottom: false,
child: LayoutBuilder(builder: (context, constraints) {
return FutureBuilder<int>(
future: getPageCount(),
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
print("none ${snapshot.data}");
return Text('none');
case ConnectionState.active:
print("active ${snapshot.data}");
return Text('active');
case ConnectionState.waiting:
print("waiting ${snapshot.data}");
return Center(child: CircularProgressIndicator());
case ConnectionState.done:
print("done ${snapshot.data}");
return buildPageView(snapshot.data);
}
});
}),
);
}).toList(),
),
);
}

Future<int> getPageCount() => Future.delayed(Duration(seconds: 3), () => 5);

Widget buildPageView(int pageCount) {
return PageView.builder(
itemBuilder: (context, position) {
return Container(child: Center(child: Text(position.toString())));
},
itemCount: pageCount,
);
}
}

最佳答案

FutureBuilder 的文档声明您不应在每次构建时都创建 future :https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html

要么在 initState 中运行 getPageCount,在字段初始化器中,要么准备一个类似于 FutureBuilder 的有状态小部件,它需要一个 future 创建函数和在它自己的 initState 中调用此函数。

编辑:使用此助手,您可以自动缓存 future

class CachingFutureBuilder<T> extends StatefulWidget {
final Future<T> Function() futureFactory;
final AsyncWidgetBuilder<T> builder;

const CachingFutureBuilder(
{Key key, @required this.futureFactory, @required this.builder})
: super(key: key);
@override
_CachingFutureBuilderState createState() => _CachingFutureBuilderState<T>();
}

class _CachingFutureBuilderState<T> extends State<CachingFutureBuilder<T>> {
Future<T> _future;

@override
void initState() {
_future = widget.futureFactory();
super.initState();
}

@override
Widget build(BuildContext context) {
return FutureBuilder<T>(
future: _future,
builder: widget.builder,
);
}
}

如果您的 getPageCount 需要大小作为输入,您可以像下面的代码一样使用该辅助小部件。诀窍是使用 ValueKey 以便 Flutter 知道重新初始化 CachingFutureBuilder。确保您没有任何大小更改动画,因为它会导致 Future 在每一帧都重新加载。

class ScrollableTabsDemo extends StatelessWidget {
Future<int> getPageCount(Size size) {
return Future.value(1);
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: LayoutBuilder(
builder: (context, constraints) {
final size = Size(constraints.maxHeight, constraints.maxWidth);
return CachingFutureBuilder<int>(
key: ValueKey(size),
futureFactory: () => getPageCount(size),
builder: (context, snapshot) {
return Text(snapshot.toString());
},
);
},
),
),
);
}
}

关于layout - 当 FutureBuilder 在 LayoutBuilder 中时 flutter 无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57148810/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com