将提供程序包StreamProvider与声明性UI结合使用

时间:2019-06-05 08:56:24

标签: flutter state-management

我一直在努力解决数据流和状态管理问题,特别是使用提供程序包。我尝试使用Future从firestore查询,但事实证明,由于Future仅期望一个值,因此不能充分利用firestore的功能。 因此,我改用Stream代替,而使用StreamProvider将数据获取到我的小部件。问题是我不知道在什么时候/如何告诉UI重建。有时流中有数据,有时却没有,我也无法真正分辨出这段时间内发生了什么。假设我想在视图繁忙时显示一个圆形进度条,那么在使用StreamProvider时该如何实现。这样做甚至有意义吗?

因此,通过filledstacks方法,当使用期货进行网络通话时,人们可以在繁忙和空闲之间切换模型状态。例如,当我们调用getPosts方法时,我们首先将状态设置为Busy,以便UI可以做出反应并可能显示加载指示符。但是,一旦异步接收到数据,我们可以将状态设置回空闲。另一方面,至少从我的理解来看,Stream只是一个不断传递数据的管道,我无法提出一种实现忙/闲状态或什至不知道这种{{ 1}}有新数据/任何数据。有什么想法吗?

这是我的Stream的一部分,应该从Firestore返回数据流。

database_service.dart

这是我的Stream<List<Expense>> getExpenses(int month, int year) { var ref = _db .collection("userData") .document(fireUser.uid) .collection("expenses") .where("month", isEqualTo: month) .where("year", isEqualTo: year) .orderBy("date", descending: true); return ref.snapshots().map((list) => list.documents.map((snap) => Expense.fromFirestore(snap)).toList()); } 使用expenses.dart的视图文件的一部分。

StreamProvider

class ExpensesPage extends StatefulWidget { @override _ExpensesPageState createState() => _ExpensesPageState(); } class _ExpensesPageState extends State<ExpensesPage> { int _month; int _year; @override void initState() { super.initState(); _month = DateTime.now().month; _year = DateTime.now().year; } @override Widget build(BuildContext context) { return StreamProvider<List<Expense>>.value( stream: locator<ExpensesProvider>().getMonthExpenses(_month, _year), initialData: [], child: StreamProvider<List<Category>>.value( stream: locator<ExpensesProvider>().getCategories(), initialData: [], child: Scaffold( body: Container( alignment: Alignment.center, color: Theme.of(context).primaryColor, padding: EdgeInsets.all(10.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ InkWell( child: DateHeader("$_month $_year"), onTap: () => _selectDate(), ), Expanded( child: ExpenseList( month: _month, year: _year, ), ) ], ), ), ), ), ); } expense_list.dart小部件使用ExpenseList中的数据。

StreamProvider

我的UI一直处于这种状态

stage

,即使我希望它会与class ExpenseList extends StatelessWidget { final _dateFormat = DateFormat.yMMMEd(); final _dbService = locator<DatabaseService>(); final int month; final int year; ExpenseList({@required this.month, @required this.year}); String getMonthName(int month) { return _dbService.monthNames[month - 1]; } @override Widget build(BuildContext context) { var expenses = Provider.of<List<Expense>>(context); var categories = Provider.of<List<Category>>(context); return expenses.length < 1 ? Center( child: Padding( padding: const EdgeInsets.all(10.0), child: Text( "You do not have any expenses for ${getMonthName(month)}, $year", style: Theme.of(context).textTheme.subhead, textAlign: TextAlign.center, ), ), ) : ListView.builder( itemBuilder: (BuildContext context, int index) { var cat = categories.firstWhere( (category) => category.id == expenses[index].category, orElse: () => Category.initial(), ); var sub = cat.subs[expenses[index].subcategory]; var amount = expenses[index].amount; var date = expenses[index].date; return ExpenseCard( expenseCategory: cat.name, expenseSubCategory: sub, expenseAmount: amount, expenseDate: _dateFormat.format(date), cardColor: Theme.of(context).cardColor); }, itemCount: expenses.length, ); } } 中的数据一起更新。

0 个答案:

没有答案