【发布时间】:2021-08-12 01:10:17
【问题描述】:
当 mainDocId 的值动态更新时,streamDemo() 不会更新 doc('$mainDocId') 的值。我想在动态更改文档 ID 时更新小部件 HomeBody(),以便我可以根据用户选择的文档检索数据。
我使用 getx 作为 SM。我尝试使用 update() 方法更新值,但不起作用。
代码如下。
控制器:
class Controller extends GetxController {
// onInit
@override
void onInit() {
finalNewsModel.bindStream(streamDemo());
super.onInit();
}
// list of document ids.
List docIdList = [
'USA',
'New York',
'Canada',
];
//
RxString mainDocId = 'USA'.obs;
// method to change document id based on docId index.
changeDocId(int index) {
mainDocId(docIdList[index]);
}
//
Rxn<List<NewsModel>> finalNewsModel = Rxn<List<NewsModel>>();
//
List<NewsModel> get newsModelList => finalNewsModel.value;
//
Stream<List<NewsModel>> streamDemo() {
return FirebaseFirestore.instance
.collection('news')
.doc('$mainDocId')
.snapshots()
.map((ds) {
var mapData = ds.data();
List mapList = mapData['list'];
List<NewsModel> modelList = [];
mapList.forEach((element) {
modelList.add(NewsModel.fromMap(element));
});
return modelList;
});
}
}
// 界面
class HomeBody extends StatefulWidget {
@override
_HomeBodyState createState() => _HomeBodyState();
}
class _HomeBodyState extends State<HomeBody> {
//
final Controller _controller = Get.put<Controller>(Controller());
@override
Widget build(BuildContext context) {
return Container(
child: Obx(() {
if (_controller.newsModelList == null) {
return Center(
child: Text(
'Please try later!',
));
} else if (_controller.newsModelList.isEmpty) {
return Text('Empty List');
} else {
return ListView.builder(
itemCount: _controller.newsModelList.length,
itemBuilder: (context, index) {
final NewsModel _newsModel = _controller.newsModelList[index];
return MyContainer(
title: _newsModel.title,
titleImage: _newsModel.titleImage,
index: index,
);
},
);
}
}),
);
}
}
底部导航栏:
bottomNavigationBar: Container(
color: Colors.grey[300],
height: 60.0,
child: Padding(
padding: EdgeInsets.all(8.0),
child: GetBuilder<Controller>(
builder: (context) => ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: _controller.docIdList.length,
itemBuilder: (context, index) {
return FavCategoryTags(
tagName: _controller.docIdList[index],
onpress: () =>_controller.changeDocId(index),
);
},
),
),
),
),
型号:
class NewsModel {
String title, titleImage, brief, source;
List aList;
NewsModel({this.title, this.titleImage, this.brief, this.aList, this.source});
factory NewsModel.fromMap(dynamic fieldData) {
return NewsModel(
title: fieldData['title'],
titleImage: fieldData['titleImage'],
brief: fieldData['brief'],
aList: fieldData['mediaDescList'],
source: fieldData['source'],
);
}
}
【问题讨论】:
-
根据我对您的代码的理解,
streamDemo()仅在onInit上被调用,这是正确的吗?如果是这样,没有任何更新是有道理的,因为流永远不会用新的mainDocId值重新实例化。您能否确认在您的执行路径中再次调用此函数是否解决了问题? -
问候 Lemos,是的,我只在 onInit() 方法中使用 streamDemo() 方法。我尝试在 BottomNavbar 的 onpressed 回调以及 changeDocid() 方法中调用 streamDemo()。它不更新。它打印更改的值但不更新。使用 Steambuilder 它会更新,但不会使用模型和 Getx。
-
好吧,我认为您将需要为此使用流构建器,我建议您应用此community question 中提出的逻辑,因为它与您的非常相似(至少具有相同的目标)并解释如何为此目的使用流构建器。
-
我确实知道如何使用 streambuilder 实现目标,但我很好奇如何将它与这个模型概念一起使用。由于根据读取,streambuilder 很昂贵。无论如何感谢您的回复。
标签: flutter dart google-cloud-firestore flutter-getx