为啥 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?