当LayoutBuilder中的FutureBuilder时,抖动无限循环

时间:2019-07-22 15:03:34

标签: layout flutter

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

PATCH

3 个答案:

答案 0 :(得分:2)

FutureBuilder的文档指出,您不应该在每个版本上都创建未来:https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html

要么在getPageCount中的initState中,在字段初始化程序中运行,要么准备一个类似于FutureBuilder的有状态小部件,该小部件将使用将来的创建函数并在自己的{{1 }}。

答案 1 :(得分:1)

您不应该在FutureBuilder中使用LayoutBuilder。可能会多次调用该构建器,因此将来每次都会调用一次。用户界面更新后,LayoutBuilder中的构建器将被调用。例如,如果您从纵向更改为横向,则将其称为建造者两次,因此也称为将来。

答案 2 :(得分:0)

每次getPageCount()构建时都会调用

LayoutBuilder。 我修改了您的代码,现在每页调用一次该函数。

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) {
          final mFuture = getPageCount();
          return SafeArea(
            top: false,
            bottom: false,
            child: LayoutBuilder(builder: (context, constraints) {
              return FutureBuilder<int>(
                  future: mFuture,
                  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,
    );
  }
}