Provider exposes incorrect values with Streams
Looks like this is precisely why ProxyProvider was introduced
https://pub.dev/documentation/provider/latest/provider/ProxyProvider-class.html Quoting the important note:
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
By wrapping AnotherWidget with MultiProvider containing ProxyProvider (as below) solves the problem
child: MultiProvider(
providers: [
Provider.value(value: _messages[index].documentID),
ProxyProvider<String, Parameters>(
builder: (context, documentId, parameters) => Parameters(documentId),
),
],
child: AnotherWidget()));
Vinayakaram Nagarajan
Updated on December 14, 2022Comments
-
Vinayakaram Nagarajan over 1 year
I am using Provider with to expose some parameters to Widgets deep down a tree. The Widgets are built from Streambuilder, i.e. Firebase documents
However, Provider does not seem to be exposing the correct value
A very simplified version of my code:
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); } }
This works perfectly fine when the Widgets are built for the first time. However, when a new document is inserted AnotherWidget shows the document Id of previous document
How do I get the correct document ID when the stream is updated?
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