当动态更新streamDemo()的值时,mainDocId ()不会更新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;
});
}
}// UI
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,
);
},
);
}
}),
);
}
}BottomNavBar:
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'],
);
}
}发布于 2021-05-30 17:54:51
这里不需要StreamBuilder。一旦一个普通的Stream绑定到一个RxType上,你就可以去了。当流数据更改时,它将更新。您只需要更新绑定调用,如下所示。
一个问题是,您应该只是初始化到一个常规的RxList。
而不是这个
Rxn<List<NewsModel>> finalNewsModel = Rxn<List<NewsModel>>();像这样初始化它。
RxList<NewsModel> finalNewsModel = <NewsModel>[].obs;你可能会失去这个吸气剂
List<NewsModel> get newsModelList => finalNewsModel.value;因为.value是不需要的,并且不会在正确初始化的RxList上工作。您可以将RxList列表视为常规列表,而不是RxString、RxInt等.这需要.value。
您的Obx现在可以在finalNewsModel上构建,并且您可以丢失空检查,因为finalNewsModel被初始化为空列表,并且永远不会为空。
Obx(() {
if (_controller.finalNewsModel.isEmpty) {
return Text('Empty List');
} else {
return Expanded(
child: ListView.builder(
itemCount: _controller.finalNewsModel.length,
itemBuilder: (context, index) {
final NewsModel _newsModel =
_controller.finalNewsModel[index];
return MyContainer(
title: _newsModel.title,
titleImage: _newsModel.titleImage,
index: index,
);
},
),
);
}
}),至于你想用你的BottomNavBar做什么
在这里,您试图通过更改Document Id来更改流本身的参数。当您绑定到onInit中的流时,它绑定到当时设置的任何Document Id。因此,除非您将其绑定到一个新的流,否则它只会更新该Document中的更改。因此,在您的示例中,只需在finalNewsModel.bindStream(streamDemo());方法中再次调用changeDocId()来更新Stream参数。
void changeDocId(int index) {
mainDocId(docIdList[index]);
finalNewsModel.bindStream(streamDemo()); // only needed because you're updating the Document Id
}您也不需要在您的GetBuilder中使用BottomNavBar,除非您需要在BottomNavBar本身上进行视觉上的更改。您所做的就是根据硬编码的RxString值更新List的值。假设您确实需要在BottomNavBar中进行重建,这将是唯一需要调用update()的场景。
我没有完整的Firebase集合结构,但我用一个简化的NewsModel对其进行了测试,并在Firebase控制台中更新了一个String,立即更新Obx小部件。调用changeDocId()将立即返回更新的Document Id的值。
编辑:而且,对于您正在做的事情,mainDocId不需要是一个可观察的字符串。流总是比原始数据类型更昂贵,因此除非您能够对其进行调整,否则最好将它变成如下所示的常规字符串。工作原理完全一样。
String mainDocId = 'USA';
// method to change document id based on docId index.
void changeDocId(int index) {
mainDocId = docIdList[index];
finalNewsModel.bindStream(streamDemo());
}发布于 2021-05-28 05:48:13
试试这个:
changeDocId(int index) {
mainDocId.value = docIdList[index];
}而不是
changeDocId(int index) {
mainDocId.value(docIdList[index]);
}我相信通过调用方法(rxVar())更新Rx并不会触发小部件的重建,而是使用赋值‘t (rxVar.value=)进行更新。
希望这能解决问题,或者至少能让你更接近修复。
https://stackoverflow.com/questions/67660041
复制相似问题