Flutter Future Builder 上架
Flutter future builder to list
我在理解 future builder 如何在 flutter 中工作时遇到了一些麻烦。我想从我以后的调用中传递一个字符串列表,我想在 SingleChildScrollView 中显示它们。
问题是,当我访问 snapshot.data
时,我无法访问列表的元素。因为在我的 SingleChildScrollView 中我有容器并且在每个容器中我想显示列表中的一个字符串。
这是我用来检索数据的 Future getData 方法。
Future<List<String>> getData () async {
List<String> data = [];
data.add("A");
data.add("B");
data.add("C");
// DEBUG
await Future.delayed(const Duration(seconds: 2), (){});
return data;
}
这是我未来的构建器,我想在其中显示每个容器中的数据。在加载中我添加了微光效果。
FutureBuilder(
builder: (context, snapshot) {
List<Widget> children;
if (snapshot.hasData) {
children = <Widget>[
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
Container(
margin: EdgeInsets.only(left: 5.w),
width: 40.w,
height: 20.h,
decoration: BoxDecoration(
color: green400,
borderRadius: BorderRadius.all(Radius.circular(5.w)),
),
),
Container(
margin: EdgeInsets.only(left: 5.w),
width: 40.w,
height: 20.h,
decoration: BoxDecoration(
color: green400,
borderRadius: BorderRadius.all(Radius.circular(5.w)),
),
),
Container(
margin: EdgeInsets.only(left: 5.w),
width: 40.w,
height: 20.h,
decoration: BoxDecoration(
color: green400,
borderRadius: BorderRadius.all(Radius.circular(5.w)),
),
),
],
),
),
];
} else if (snapshot.hasError) {
children = <Widget>[
const Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text('Error: ${snapshot.error}'),
)
];
} else {
children = <Widget>[
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
Shimmer.fromColors(
baseColor: Colors.grey.shade200,
highlightColor: Colors.grey.shade300,
child: Container(
margin: EdgeInsets.only(left: 5.w),
width: 40.w,
height: 20.h,
decoration: BoxDecoration(
color: green400,
borderRadius: BorderRadius.all(Radius.circular(5.w)),
),
),
),
Shimmer.fromColors(
baseColor: Colors.grey.shade200,
highlightColor: Colors.grey.shade300,
child: Container(
margin: EdgeInsets.only(left: 5.w),
width: 40.w,
height: 20.h,
decoration: BoxDecoration(
color: green400,
borderRadius: BorderRadius.all(Radius.circular(5.w)),
),
),
),
Shimmer.fromColors(
baseColor: Colors.grey.shade200,
highlightColor: Colors.grey.shade300,
child: Container(
margin: EdgeInsets.only(left: 5.w),
width: 40.w,
height: 20.h,
decoration: BoxDecoration(
color: green400,
borderRadius: BorderRadius.all(Radius.circular(5.w)),
),
),
),
],
),
),
];
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: children,
),
);
},
future: getData(),
),
那么我可以通过这种方式访问我的字符串列表中的元素吗?
当您声明一个 FutureBuilder
时,您还必须传递它的数据类型。在这种情况下它将是:
FutureBuilder<List<String>>(
future: getData(),
builder: (context,snapshot){
return ...;
}
)
如果您不声明其数据类型,您的 snapshot
将被视为 AsyncDataSnapshot<dynamic>
而不是 AsyncDataSnapshot<List<String>>
。
如@piskink 所述,使用 ListView.builder
效率更高。
body: FutureBuilder<List<String>?>(
future: getData(),
builder: (context, snapshot) {
if (snapshot.hasData &&
snapshot.connectionState == ConnectionState.done) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return Text(snapshot.data?[index] ?? "got null");
},
);
}
/// handles others as you did on question
else {
return CircularProgressIndicator();
}
},
如果您仍想使用 SingleChildScrollView
,您可以生成类似
的项目
return Column(
children: List.generate(
snapshot.data!.length,
(index) => Text(snapshot.data?[index] ?? "got null"),
),
);
查看有关 async-await and Future 的更多信息。
这是具有 Null Safty 的 FutureBuilder 的完整示例
如果您遇到这些错误:
(getter 'length' 没有为类型 'Object' 定义。)
(未为类型 'Object' 定义运算符“[]”。)
这是修复↓↓↓↓↓
修复和重要说明:
您必须 select 将接收的未来数据的数据类型。
右:FutureBuilder()
错误:FutureBuilder()
完整的简单示例:
import 'package:flutter/material.dart';
class FutureExample extends StatelessWidget {
const FutureExample({Key? key}) : super(key: key);
Future<List<String>> getData() async{
await Future.delayed(
const Duration(seconds:2)
);
return ["I'm Ramy","I'm Yasser", "I'm Ahmed", "I'm Yossif",];
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureBuilder<List<String>>(
future: getData(),
builder: (context, snapshot) {
return snapshot.connectionState == ConnectionState.waiting
? const CircularProgressIndicator()
: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: List.generate(snapshot.data!.length,
(index) {
return Text(snapshot.data?[index] ?? "null") ;
},
),
);
},
),
),
);
}
}
我在理解 future builder 如何在 flutter 中工作时遇到了一些麻烦。我想从我以后的调用中传递一个字符串列表,我想在 SingleChildScrollView 中显示它们。
问题是,当我访问 snapshot.data
时,我无法访问列表的元素。因为在我的 SingleChildScrollView 中我有容器并且在每个容器中我想显示列表中的一个字符串。
这是我用来检索数据的 Future getData 方法。
Future<List<String>> getData () async {
List<String> data = [];
data.add("A");
data.add("B");
data.add("C");
// DEBUG
await Future.delayed(const Duration(seconds: 2), (){});
return data;
}
这是我未来的构建器,我想在其中显示每个容器中的数据。在加载中我添加了微光效果。
FutureBuilder(
builder: (context, snapshot) {
List<Widget> children;
if (snapshot.hasData) {
children = <Widget>[
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
Container(
margin: EdgeInsets.only(left: 5.w),
width: 40.w,
height: 20.h,
decoration: BoxDecoration(
color: green400,
borderRadius: BorderRadius.all(Radius.circular(5.w)),
),
),
Container(
margin: EdgeInsets.only(left: 5.w),
width: 40.w,
height: 20.h,
decoration: BoxDecoration(
color: green400,
borderRadius: BorderRadius.all(Radius.circular(5.w)),
),
),
Container(
margin: EdgeInsets.only(left: 5.w),
width: 40.w,
height: 20.h,
decoration: BoxDecoration(
color: green400,
borderRadius: BorderRadius.all(Radius.circular(5.w)),
),
),
],
),
),
];
} else if (snapshot.hasError) {
children = <Widget>[
const Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text('Error: ${snapshot.error}'),
)
];
} else {
children = <Widget>[
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
Shimmer.fromColors(
baseColor: Colors.grey.shade200,
highlightColor: Colors.grey.shade300,
child: Container(
margin: EdgeInsets.only(left: 5.w),
width: 40.w,
height: 20.h,
decoration: BoxDecoration(
color: green400,
borderRadius: BorderRadius.all(Radius.circular(5.w)),
),
),
),
Shimmer.fromColors(
baseColor: Colors.grey.shade200,
highlightColor: Colors.grey.shade300,
child: Container(
margin: EdgeInsets.only(left: 5.w),
width: 40.w,
height: 20.h,
decoration: BoxDecoration(
color: green400,
borderRadius: BorderRadius.all(Radius.circular(5.w)),
),
),
),
Shimmer.fromColors(
baseColor: Colors.grey.shade200,
highlightColor: Colors.grey.shade300,
child: Container(
margin: EdgeInsets.only(left: 5.w),
width: 40.w,
height: 20.h,
decoration: BoxDecoration(
color: green400,
borderRadius: BorderRadius.all(Radius.circular(5.w)),
),
),
),
],
),
),
];
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: children,
),
);
},
future: getData(),
),
那么我可以通过这种方式访问我的字符串列表中的元素吗?
当您声明一个 FutureBuilder
时,您还必须传递它的数据类型。在这种情况下它将是:
FutureBuilder<List<String>>(
future: getData(),
builder: (context,snapshot){
return ...;
}
)
如果您不声明其数据类型,您的 snapshot
将被视为 AsyncDataSnapshot<dynamic>
而不是 AsyncDataSnapshot<List<String>>
。
如@piskink 所述,使用 ListView.builder
效率更高。
body: FutureBuilder<List<String>?>(
future: getData(),
builder: (context, snapshot) {
if (snapshot.hasData &&
snapshot.connectionState == ConnectionState.done) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return Text(snapshot.data?[index] ?? "got null");
},
);
}
/// handles others as you did on question
else {
return CircularProgressIndicator();
}
},
如果您仍想使用 SingleChildScrollView
,您可以生成类似
return Column(
children: List.generate(
snapshot.data!.length,
(index) => Text(snapshot.data?[index] ?? "got null"),
),
);
查看有关 async-await and Future 的更多信息。
这是具有 Null Safty 的 FutureBuilder 的完整示例
如果您遇到这些错误:
(getter 'length' 没有为类型 'Object' 定义。)
(未为类型 'Object' 定义运算符“[]”。)
这是修复↓↓↓↓↓
修复和重要说明:
您必须 select 将接收的未来数据的数据类型。
右:FutureBuilder
- ()
错误:FutureBuilder()
完整的简单示例:
import 'package:flutter/material.dart';
class FutureExample extends StatelessWidget {
const FutureExample({Key? key}) : super(key: key);
Future<List<String>> getData() async{
await Future.delayed(
const Duration(seconds:2)
);
return ["I'm Ramy","I'm Yasser", "I'm Ahmed", "I'm Yossif",];
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureBuilder<List<String>>(
future: getData(),
builder: (context, snapshot) {
return snapshot.connectionState == ConnectionState.waiting
? const CircularProgressIndicator()
: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: List.generate(snapshot.data!.length,
(index) {
return Text(snapshot.data?[index] ?? "null") ;
},
),
);
},
),
),
);
}
}