Flutter 如何在颤振中最好地反映受未来影响的对象的状态

Flutter 如何在颤振中最好地反映受未来影响的对象的状态,flutter,dart,Flutter,Dart,我有一个类型为list的值,我将在ListViewBuilder上使用它 我有一个条件,检查列表的长度是否为0或更多,以便在列表中没有可用项时显示空状态小部件,并在列表中有项时显示ListViewBuilder 运行逻辑实际上表明它是有效的,但我的问题是,由于列表对象的长度从0开始,它总是先绘制我的“空状态”小部件,但当我的未来函数在列表上完成递增时,它会快速绘制实际的ListViewBuilder。虽然它可以工作,但即使列表中确实有项目,用户也能快速看到“空状态”的体验非常不和谐 希望你们能帮

我有一个类型为list的值,我将在ListViewBuilder上使用它

我有一个条件,检查列表的长度是否为0或更多,以便在列表中没有可用项时显示空状态小部件,并在列表中有项时显示ListViewBuilder

运行逻辑实际上表明它是有效的,但我的问题是,由于列表对象的长度从0开始,它总是先绘制我的“空状态”小部件,但当我的未来函数在列表上完成递增时,它会快速绘制实际的ListViewBuilder。虽然它可以工作,但即使列表中确实有项目,用户也能快速看到“空状态”的体验非常不和谐

希望你们能帮我一个办法,我只能显示我的名单上的任何一个状态,而不必通过从零的初始状态

下面是我正在谈论的一个表示,您可以看到我的三个状态:NULL(白色),==0(蓝色),>=1(绿色)

编辑:在下面添加了示例代码

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class MainProvider extends ChangeNotifier {
  List<String> list = <String>[];

  MainProvider() {
    initList();
  }

  initList() async {
    // CODE BELOW IS TO SIMULATE MAKING DATABASE CALLS
    for (int i = 1; i <= 5; i++) {
      await Future.delayed(Duration(milliseconds: 800), () {
        addToList('String');
      });
    }
  }

  addToList(String string) {
    list.add(string);
    notifyListeners();
  }
}

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

class AppIndex extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: AppProvider(),
    );
  }
}

class AppProvider extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<MainProvider>(
      create: (context) => MainProvider(),
      child: AppContent(),
    );
  }
}

class AppContent extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var mainProvider = Provider.of<MainProvider>(context);

    return Scaffold(
      appBar: AppBar(),
      body: mainProvider.list == null
          ? Container(
              color: Colors.red,
              child: Center(
                child: Center(
                  child: Text(
                    'NULL',
                  ),
                ),
              ),
            )
          : mainProvider.list.length == 0
              ? Container(
                  color: Colors.blue,
                  child: Center(
                    child: Text(
                      mainProvider.list.length.toString(),
                      style: TextStyle(fontSize: 32.0),
                    ),
                  ),
                )
              : mainProvider.list.length >= 0
                  ? Container(
                      color: Colors.green,
                      child: Center(
                        child: Text(
                          mainProvider.list.length.toString(),
                          style: TextStyle(fontSize: 32.0),
                        ),
                      ),
                    )
                  : Container(
                      color: Colors.red,
                      child: Center(
                        child: Text(
                          mainProvider.list.length.toString(),
                          style: TextStyle(fontSize: 32.0),
                        ),
                      ),
                    ),
    );
  }
}
导入“包装:颤振/材料.省道”;
导入“包:provider/provider.dart”;
类MainProvider扩展了ChangeNotifier{
列表=[];
MainProvider(){
initList();
}
initList()异步{
//下面的代码模拟进行数据库调用
对于(int i=1;i runApp(AppIndex());
类AppIndex扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
主页:AppProvider(),
);
}
}
类AppProvider扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回ChangeNotifierProvider(
create:(context)=>MainProvider(),
子项:AppContent(),
);
}
}
类AppContent扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
var mainProvider=Provider.of(上下文);
返回脚手架(
appBar:appBar(),
正文:mainProvider.list==null
?容器(
颜色:颜色,红色,
儿童:中心(
儿童:中心(
子:文本(
“空”,
),
),
),
)
:mainProvider.list.length==0
?容器(
颜色:颜色,蓝色,
儿童:中心(
子:文本(
mainProvider.list.length.toString(),
样式:TextStyle(fontSize:32.0),
),
),
)
:mainProvider.list.length>=0
?容器(
颜色:颜色。绿色,
儿童:中心(
子:文本(
mainProvider.list.length.toString(),
样式:TextStyle(fontSize:32.0),
),
),
)
:容器(
颜色:颜色,红色,
儿童:中心(
子:文本(
mainProvider.list.length.toString(),
样式:TextStyle(fontSize:32.0),
),
),
),
);
}
}
在我的代码中,我使用Future函数调用数据库项 在上面的示例代码中,我故意添加了一个 延迟以模拟数据库调用时间


鉴于你的评论,我认为这样做可以:

class _HomePageState extends State<HomePage> {
  Future<List<Item>> _items;

  @override
  void initState() {
    super.initState();
    // here maybe you won't use the server side, but some local storage
    _items = Web.fetchItems();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<List<Item>>(
      future: _items,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          if (_items.isEmpty) {
            return _MyCallToActionButtonLayout();
          }
          return Scaffold(
            appBar: AppBar(
              title: Text('My title'),
            ),
            body: buildListView(snapshot.data)),
          );
        } else if (snapshot.hasError) {
          return Text("${snapshot.error}");
        } else {
          return Scaffold(body: Center(child: CircularProgressIndicator()));
        }
      },
    );
  }

class\u HomePageState扩展状态{
未来项目;
@凌驾
void initState(){
super.initState();
//在这里,您可能不会使用服务器端,而是使用一些本地存储
_items=Web.fetchItems();
}
@凌驾
小部件构建(构建上下文){
回归未来建设者(
未来:_项目,
生成器:(上下文,快照){
if(snapshot.hasData){
如果(_items.isEmpty){
返回_MyCallToActionButtonLayout();
}
返回脚手架(
appBar:appBar(
标题:文本(“我的标题”),
),
正文:buildListView(snapshot.data)),
);
}else if(snapshot.hasrerror){
返回文本(“${snapshot.error}”);
}否则{
返回脚手架(主体:中心(子对象:环形推进器());
}
},
);
}

分享您的代码,以便更好地理解。我将用示例代码更新我的问题。Thanks@AverageCoder如果你通过互联网检索你的列表,连接需要25秒才能给你第一个项目呢?那么你要向用户展示什么呢?我的意思是,你在这里展示的内容对我来说似乎是正确的。标准方法是h是用FutureBuilder显示一个循环进度指示器
中心(子项:CircularProgressIndicator())
,例如。另外,从UI的角度来看,null和0是相同的状态。您可以显示一张带有“您的列表为空”的图片消息类型,如Material DesignHi@Alessio推荐的,感谢您的帮助。您是对的,但我在这里试图实现的是,当列表上没有可用的项目时,我将显示一个调用操作按钮,邀请用户创建对象。但每当应用程序重新启动时,它总是显示我的调用操作按钮简单地说,即使用户以前已经创建过对象。我想这更像是一个与Flatter的系统设计咨询?:)顺便说一句,我正在为我的列表对象使用提供程序,并在操作它时感谢您的帮助!我现在正在重新考虑我的设计,并附上您提供的备注。干杯!
class _HomePageState extends State<HomePage> {
  Future<List<Item>> _items;

  @override
  void initState() {
    super.initState();
    // here maybe you won't use the server side, but some local storage
    _items = Web.fetchItems();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<List<Item>>(
      future: _items,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          if (_items.isEmpty) {
            return _MyCallToActionButtonLayout();
          }
          return Scaffold(
            appBar: AppBar(
              title: Text('My title'),
            ),
            body: buildListView(snapshot.data)),
          );
        } else if (snapshot.hasError) {
          return Text("${snapshot.error}");
        } else {
          return Scaffold(body: Center(child: CircularProgressIndicator()));
        }
      },
    );
  }