Provider 使用 Streams 公开不正确的值
Provider exposes incorrect values with Streams
我正在使用 Provider with 将一些参数暴露给树深处的小部件。小部件是从 Streambuilder 构建的,即 Firebase 文档
但是,Provider 似乎没有公开正确的值
我的代码的一个非常简化的版本:
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:provider/provider.dart';
class Parameters {
Parameters(this.documentId);
final String documentId;
}
class Widget1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: mystream, //Query the Firebase for a bunch of Documents
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text('Error processing data feed');
}
switch (snapshot.connectionState) {
case ConnectionState.waiting:
{
return CircularProgressIndicator();
}
break;
default:
{
var _messages = snapshot.data.documents;
return ListView.builder(
itemCount: _messages.length,
itemBuilder: (context, index) {
return Provider<Parameters>(
builder: (context) =>
Parameters(_messages[index].documentID),
child: AnotherWidget());
});
}
}
});
}
}
class AnotherWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
Parameters param = Provider.of<Parameters>(context);
return Text(param.documentId);
}
}
第一次构建小部件时,这工作得很好。但是,当插入新文档时,AnotherWidget 显示前一个文档的文档 ID
如何在更新流时获取正确的文档 ID?
Note: I am aware I can simply pass the document as a parameter. However I need the parameter deep down the widget tree of AnotherWidget
看起来这正是引入 ProxyProvider 的原因
https://pub.dev/documentation/provider/latest/provider/ProxyProvider-class.html
引用重要提示:
As opposed to the builder parameter of Provider, builder may be called more than once. It will be called once when the widget is mounted, then once whenever any of the InheritedWidget which ProxyProvider depends emits an update
通过使用包含 ProxyProvider 的 MultiProvider 包装 AnotherWidget(如下所示)解决了问题
child: MultiProvider(
providers: [
Provider.value(value: _messages[index].documentID),
ProxyProvider<String, Parameters>(
builder: (context, documentId, parameters) => Parameters(documentId),
),
],
child: AnotherWidget()));
我正在使用 Provider with 将一些参数暴露给树深处的小部件。小部件是从 Streambuilder 构建的,即 Firebase 文档
但是,Provider 似乎没有公开正确的值
我的代码的一个非常简化的版本:
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:provider/provider.dart';
class Parameters {
Parameters(this.documentId);
final String documentId;
}
class Widget1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: mystream, //Query the Firebase for a bunch of Documents
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text('Error processing data feed');
}
switch (snapshot.connectionState) {
case ConnectionState.waiting:
{
return CircularProgressIndicator();
}
break;
default:
{
var _messages = snapshot.data.documents;
return ListView.builder(
itemCount: _messages.length,
itemBuilder: (context, index) {
return Provider<Parameters>(
builder: (context) =>
Parameters(_messages[index].documentID),
child: AnotherWidget());
});
}
}
});
}
}
class AnotherWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
Parameters param = Provider.of<Parameters>(context);
return Text(param.documentId);
}
}
第一次构建小部件时,这工作得很好。但是,当插入新文档时,AnotherWidget 显示前一个文档的文档 ID
如何在更新流时获取正确的文档 ID?
Note: I am aware I can simply pass the document as a parameter. However I need the parameter deep down the widget tree of AnotherWidget
看起来这正是引入 ProxyProvider 的原因
https://pub.dev/documentation/provider/latest/provider/ProxyProvider-class.html 引用重要提示:
As opposed to the builder parameter of Provider, builder may be called more than once. It will be called once when the widget is mounted, then once whenever any of the InheritedWidget which ProxyProvider depends emits an update
通过使用包含 ProxyProvider 的 MultiProvider 包装 AnotherWidget(如下所示)解决了问题
child: MultiProvider(
providers: [
Provider.value(value: _messages[index].documentID),
ProxyProvider<String, Parameters>(
builder: (context, documentId, parameters) => Parameters(documentId),
),
],
child: AnotherWidget()));