如何在 Flutter 的同一屏幕中管理两个带有数据的 ListView
Posted
技术标签:
【中文标题】如何在 Flutter 的同一屏幕中管理两个带有数据的 ListView【英文标题】:How to manage two ListView with data in firestore in the same screen in Flutter 【发布时间】:2020-01-16 02:20:51 【问题描述】:我正在构建一个 Flutter 应用程序,我有一个带有 2 个 ListView 的屏幕。数据源是一个 Firestore 数据库,两个列表都相同,但是一个列表仅显示图像,而另一个列表显示图像和其他信息。
我设法找到了一个显示两个列表的解决方案,但它似乎不是最有效的,因为我相信我正在下载相同的数据 2 次。你有什么建议可以让它变得更好吗???
请看下面的代码
final _firestore = Firestore.instance;
class ItemPage extends StatefulWidget
@override
_ItemPageState createState() => _ItemPageState();
class _ItemPageState extends State<ItemPage>
bool showSpinner = false;
@override
Widget build(BuildContext context)
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
heroTag: 'itemppage',
transitionBetweenRoutes: false,
middle: Text(
appData.categoryName,
style: kSendButtonTextStyle,
),
),
child: Scaffold(
backgroundColor: kColorPrimary,
body: ModalProgressHUD(
inAsyncCall: showSpinner,
child: Column(
children: <Widget>[
Expanded(
child: ItemList(),
),
Container(
height: 80.0,
child: ItemListBottomScroll(),
)
],
),
),
),
);
class ItemList extends StatelessWidget
@override
Widget build(BuildContext context)
return StreamBuilder<QuerySnapshot>(
stream: _firestore
.collection('books')
.snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot)
if (snapshot.hasError) return new Text('Error: $snapshot.error');
switch (snapshot.connectionState)
case ConnectionState.waiting:
return new Text(
'Loading...',
style: kSendButtonTextStyle,
);
default:
return new PageView(
scrollDirection: Axis.horizontal,
children:
snapshot.data.documents.map((DocumentSnapshot document)
return SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.all(10.0),
child: Stack(
children: <Widget>[
CachedNetworkImage(
imageUrl: document['url'],
placeholder: (context, url) =>
new CircularProgressIndicator(),
errorWidget: (context, url, error) =>
new Icon(Icons.error),
width: MediaQuery.of(context).size.width - 20,
height:
(MediaQuery.of(context).size.width - 20),
fit: BoxFit.cover),
Positioned(
bottom: 0.0,
right: 0.0,
child: IconButton(
color: kColorAccent.withOpacity(0.8),
iconSize: 50.0,
icon: Icon(Icons.add_circle),
onPressed: ()
print(document['name'] +
document.documentID +
' clicked');
,
),
),
],
),
),
Padding(
padding: const EdgeInsets.only(
left: 10.0, right: 10.0, bottom: 10.0),
child: Row(
children: <Widget>[
Expanded(
child: Text(
document['name'],
style: kSendButtonTextStyle,
),
flex: 3,
),
Expanded(
child: Text(
appData.currency + document['price'],
textAlign: TextAlign.right,
style: kDescriptionTextStyle,
),
flex: 1,
),
],
),
),
Padding(
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
child: Container(
child: Text(
document['description'],
style: kDescriptionTextStyle,
),
width: double.infinity,
),
)
],
),
);
).toList(),
);
,
);
class ItemListBottomScroll extends StatelessWidget
@override
Widget build(BuildContext context)
return StreamBuilder<QuerySnapshot>(
stream: _firestore
.collection('books')
.snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot)
if (snapshot.hasError) return new Text('Error: $snapshot.error');
switch (snapshot.connectionState)
case ConnectionState.waiting:
return new Text('Loading...');
default:
return new ListView(
scrollDirection: Axis.horizontal,
children:
snapshot.data.documents.map((DocumentSnapshot document)
return Stack(
children: <Widget>[
Container(
height: 80.0,
width: 90.0,
padding: EdgeInsets.only(left: 10.0),
child: GestureDetector(
onTap: ()
print(document['name'] +
document.documentID +
' bottom clicked');
,
child: new CachedNetworkImage(
imageUrl: document['url'],
placeholder: (context, url) =>
new CircularProgressIndicator(),
errorWidget: (context, url, error) =>
new Icon(Icons.error),
fit: BoxFit.cover),
),
),
],
);
).toList(),
);
,
);
【问题讨论】:
【参考方案1】:为了从同一个Stream
读取这两个信息,您需要先将其公开为广播流:
final streamQuery = _firestore
.collection('books')
.snapshots()
.asBroadcastStream();
return StreamBuilder<QuerySnapshot>(
stream: streamQuery,
builder: ...
【讨论】:
以上是关于如何在 Flutter 的同一屏幕中管理两个带有数据的 ListView的主要内容,如果未能解决你的问题,请参考以下文章