为啥 futureBuilder 返回一个空值?

Posted

技术标签:

【中文标题】为啥 futureBuilder 返回一个空值?【英文标题】:Why does futureBuilder return a null value?为什么 futureBuilder 返回一个空值? 【发布时间】:2021-06-28 00:26:25 【问题描述】:

当我尝试在我的主页中获取一个对象时,我没有收到错误,但即使我在下一个屏幕中使用相同的方法从数据库中显示我的对象,FutureBuilder 也无法获取任何价值。

@override
  Widget build(BuildContext context) 
    return WillPopScope(
      child: SafeArea(
        child: Scaffold(
          backgroundColor: kColorTheme1,
          appBar: AppBar(
            centerTitle: true,
            automaticallyImplyLeading: false,
            elevation: 20,
            backgroundColor: Color(0xFFF2C3D4).withOpacity(1),
            title:TitleBorderedText(title:"Sevimli Yemekler", textColor: Color(0xFFFFFB00)),
            actions: [
              CircleAvatar(
                radius: 27,
                backgroundColor: Colors.transparent,
                backgroundImage: AssetImage(kCuttedLogoPath),
              ),
            ],
          ),
          body: FutureBuilder<Map>(
            future: HiveHelper().getCategoryModels(),
            builder: (BuildContext context,AsyncSnapshot<Map> snapshot)
              if(snapshot.hasData) 
                _list = snapshot.data.values.toList();
              
              Future.delayed(Duration(milliseconds: 200));
              return Container(
                decoration: BoxDecoration(
                  image: DecorationImage(
                    image: AssetImage(kBGWithLogoOpacity),
                    fit: BoxFit.cover,
                  ),
                ),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: [
                    Expanded(
                      child:GridView.builder(
                          scrollDirection: Axis.vertical,
                          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
                          itemCount: _list.length+1,
                          itemBuilder: (context,index)
                            if(_list.length==0)
                              return EmptyCard(where: "homeScreen",);
                            
                            if(_flag==1)
                              return EmptyCard(where: "homeScreen",);
                            
                            if(index==_list.length-1)
                              _flag=1;
                              CategoryModel categoryModel = _list[index];
                              return CategoryCard(category: categoryModel);
                            
                            else
                              CategoryModel categoryModel =_list[index];
                              return CategoryCard(category: categoryModel);
                            
                          
                      ),
                    ),
                    Column(
                      mainAxisAlignment: MainAxisAlignment.end,
                      crossAxisAlignment: CrossAxisAlignment.stretch,
                      children: [
                        Padding(
                          padding: EdgeInsets.all(10),
                          child: Container(
                            decoration: BoxDecoration(
                              border: Border.all(style: BorderStyle.solid),
                              color: kColorTheme7,
                              borderRadius: BorderRadius.circular(40),
                            ),
                            child: TextButton(
                                onPressed: ()
                                  showModalBottomSheet(
                                    isDismissible: false,
                                    enableDrag: false,
                                    context: context,
                                    builder: (BuildContext context)=> AddMenuScreen(buttonText: "Menü Ekle",route: "homeScreen",),
                                  );
                                ,
                                child: TitleBorderedText(title: "LEZZET GRUBU EKLE",textColor: Colors.white,)
                            ),
                          ),
                        ),
                      ],
                    )
                  ],
                ),
              );
            ,
          ),
        ),
      ),
      onWillPop: ()async
        var response = await showAlertDialog(context);
        print(response);
        return response;
      ,
    );
  

我可以在这里显示我的对象而不会出现任何错误。我在下面使用相同的数据库和相同的构建器,但我可以取值。

@override
  Widget build(BuildContext context) 
    return SafeArea(
      child: Scaffold(
        body: FutureBuilder<Map>(
          future: HiveHelper().getCategoryModel(widget.categoryId),
          builder: (BuildContext context,AsyncSnapshot<Map> snapshot) 
            if(snapshot.hasData) 
              _list=snapshot.data.values.toList();
            
            Future.delayed(Duration(milliseconds: 200));
            return  Scaffold(
              appBar: AppBar(
                automaticallyImplyLeading: false,
                centerTitle: true,
                title: BorderedText(
                  child:Text(
                    _list[4],
                    style: TextStyle(
                        color: Color(0XFFFFFB00),
                        fontSize: 30,
                        fontFamily: "OpenSans"
                    ),
                  ),
                  strokeWidth: 5,
                  strokeColor: Colors.black,
                ),
                elevation: 5,
                backgroundColor: Color(0xFFF2C3D4).withOpacity(1),
                leading: IconButton(
                  icon: Icon(Icons.arrow_back),
                  onPressed: ()
                    Navigator.pop(context);
                  ,
                  iconSize: 40,
                  color: Color(0xFFA2000B),
                ),
                actions: [
                  CircleAvatar(
                    radius: 27,
                    backgroundColor: Colors.transparent,
                    backgroundImage: AssetImage("images/cuttedlogo.PNG"),
                  )
                ],
              ),
              body:Container(
                decoration: BoxDecoration(
                  image: DecorationImage(
                    image: AssetImage("images/logoBGopacity.png"),
                    fit: BoxFit.cover,
                  ),
                ),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: [
                    Expanded(
                      child: GridView.builder(
                          scrollDirection: Axis.vertical,
                          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
                          itemCount:_list[5].length+1,
                          itemBuilder: (context,index)
                            if(_list[5].length==0)
                              return EmptyCard(where: "subCategoryScreen",categoryId: widget.categoryId,);
                            
                            if(_flag==1)
                              return EmptyCard(where: "homeScreen",);
                            
                            if(index==_list[5].length-1)
                              _flag=1;
                              SubCategoryModel subCategoryModel =SubCategoryModel();
                              return SubCategoryCard(subCategoryCardId:index,subCategoryId:subCategoryModel.subCategoryId,subcategoryName: subCategoryModel.subCategoryName,
                                subCategoryImagePath:subCategoryModel.subCategoryImagePath,
                                subCategoryCardColor: subCategoryModel.categoryColor,);
                            
                            else
                              SubCategoryModel subCategoryModel =SubCategoryModel();
                              return SubCategoryCard(subCategoryCardId:index,subCategoryId:subCategoryModel.subCategoryId,subcategoryName: subCategoryModel.subCategoryName,
                                subCategoryImagePath:subCategoryModel.subCategoryImagePath,
                                subCategoryCardColor: subCategoryModel.categoryColor,);
                            
                          
                      ),
                    ),
                    Column(
                      mainAxisAlignment: MainAxisAlignment.end,
                      crossAxisAlignment: CrossAxisAlignment.stretch,
                      children: [
                        Padding(
                          padding: EdgeInsets.all(10),
                          child: Container(
                            decoration: BoxDecoration(
                              border: Border.all(style: BorderStyle.solid),
                              color: kColorTheme7,
                              borderRadius: BorderRadius.circular(40),
                            ),
                            child: TextButton(
                              onPressed: ()
                                showModalBottomSheet(
                                  isDismissible: false,
                                  enableDrag: false,
                                  context: context,
                                  builder: (BuildContext context)=> AddMenuScreen(categoryId:widget.categoryId,buttonText: "Tarif Ekle", route:"subCategoryScreen"),
                                );
                              ,
                              child: BorderedText(
                                strokeWidth: 5,
                                strokeColor: Colors.black,
                                child:Text("Tarif Ekle",style: TextStyle(
                                  color: Colors.white,
                                  fontFamily:'OpenSans',
                                  fontSize:30,
                                ),
                              ),
                            ),
                          ),
                        ),
                      ),
                    ],
                  )
                ],
              ),
            ),
          );
          
        ),
      ),
    );
  
class HiveHelper

  void addCategoryModel(CategoryModel categoryModel)async
    var box = await Hive.openBox('categoryModelsInBox');
    await box.add(categoryModel);
    await Hive.close();
  
  Future <Map> getCategoryModels()async
    var box = await Hive.openBox('categoryModelsInBox');
    var boxToMap=box.toMap();
    return boxToMap;
  

  Future <Map> getCategoryModel(int index) async 
    var box = await Hive.openBox('categoryModelsInBox');
    var boxToMap=box.toMap();
    return boxToMap[index];
  

  void addSubCategory(SubCategoryModel subCategoryModel, key)async
    var box = await Hive.openBox('categoryModelsInBox');
    box.put(subCategoryModel,key);
  

这是我的蜂巢课程。我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

不要在 FutureBuilder 的“future:”参数中创建未来。正如精美手册的第一大段所说:

未来一定是更早获得的,例如在 State.initState、State.didUpdateWidget 或 State.didChangeDependencies 期间。在构造 FutureBuilder 时,不能在 State.build 或 StatelessWidget.build 方法调用期间创建它。如果 Future 与 FutureBuilder 是同时创建的,那么每次 FutureBuilder 的 parent 重建时,异步任务都会重新启动。

一般准则是假设每个构建方法都可以在每一帧被调用,并将省略的调用视为优化。

https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html

【讨论】:

【参考方案2】:

我不确定,但你可以试试:

Future <Map> getCategoryModel(int index) async 
    var box = await Hive.openBox('categoryModelsInBox');
    var boxToMap=box.toMap();
    return boxToMap["$index"];

【讨论】:

这可能会在每次构建时重新调用,如果是这样,仍然会被破坏。 @RandalSchwartz 我担心这不是导致空错误的原因

以上是关于为啥 futureBuilder 返回一个空值?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 FutureBuilder snapshot.data 返回“Post 实例”而不是 json?

为啥`return a or b`是Ruby中的空值表达式错误?

为啥它返回一个空值?!!(客户端/服务器应用程序)

为啥我的数据表单元格返回空值?

为啥 eloquent orm 上的查询语句结果返回空值

为啥futureBuilder有时会卡在进度加载器上?