Description
I have a page(InitialElementResultScreen) that has to wait for several operations to be done in the InitialElementResultNotifier to display the rest of the page.
Code that works
My InitialElementResultScreen:
class InitialElementResultScreen extends StatelessWidget {
final String title;
InitialElementResultScreen({
Key key,
@required this.title,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBarWidget.withoutMenu(title: title),
body: _buildBody(context),
);
}
Widget _buildBody(BuildContext context){
// => For use variable in my screen I use the notifier.
var _initialElementResultProvider = Provider.of<InitialElementResultNotifier>(context);
return SingleChildScrollView(
child: Column(
children: [
ContainerComponent(
colorContainer: AppColors.backgroundLightBasic,
children: [
FutureBuilder(
future: _initialElementResultProvider.myFuture,
builder: (context, snapshot){
if(!snapshot.hasData) {
return Text('loading');
}else{
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// ... some widgets
],
);
}
}
)
],
),
],
),
);
}
}
When I call my InitialElementResultScreen :
ChangeNotifierProvider<InitialElementResultNotifier>(
create: (BuildContext context) => InitialElementResultNotifier(getData: data)
)
My InitialElementResultNotifier receives external data directly in its constructor. It converts them to objects so that I can do operations on them.
My InitialElementResultNotifier :
class InitialElementResultNotifier with ChangeNotifier{
// External Notifier
// ---------------------------------------------------------------------------
// Variables
// ---------------------------------------------------------------------------
FormInitialElementModel dataReceived;
Future myFuture;
// Constructor
// ---------------------------------------------------------------------------
InitialElementResultNotifier({
@required String getData,
}){
_initialise(getData);
}
// Initialisation
// ---------------------------------------------------------------------------
Future _initialise(String getData) async{
print('--- initialise');
dataReceived = await _convertDataReceived(getData);
myFuture = loadingInitialElementData();
}
// Functions public
// ---------------------------------------------------------------------------
Future<void> loadingInitialElementData() async
{
print('---------------------- dataReceived');
print(dataReceived); // => I see my data in the console
// ... some operations
}
}
Code that does not work
In my function which loadingInitialElementData (), I would like to have access to another notifier. The notifier LoaderNotifier manages the display of different messages depending on its state that I will change according to my operations in the loadingInitialElementData() function.
For this I will use a proxy Provider. So now I call my InitialElementResultScreen like that:
ChangeNotifierProvider<LoaderNotifier>(
create: (BuildContext context) => LoaderNotifier()
),
ProxyProvider<LoaderNotifier, InitialElementResultNotifier>(
update: (BuildContext context, LoaderNotifier loaderNotifier, InitialElementResultNotifier initialElementResultNotifier) {
return InitialElementResultNotifier(
getData: data,
loaderNotifier: loaderNotifier
);
}
),
I will update my InitialElementResultNotifier:
All the code is the same except 3 lines to be able to call on my other Notifier. I marked the lines as comments in the code
class InitialElementResultNotifier with ChangeNotifier{
// External Notifier
// ---------------------------------------------------------------------------
LoaderNotifier _loaderNotifier; // => New line !
// Variables
// ---------------------------------------------------------------------------
FormInitialElementModel dataReceived;
Future myFuture;
// Constructor
// ---------------------------------------------------------------------------
InitialElementResultNotifier({
@required String getData,
LoaderNotifier loaderNotifier, // => New line !
}){
_loaderNotifier = loaderNotifier; // => New line !
_initialise(getData);
}
// Initialisation
// ---------------------------------------------------------------------------
Future _initialise(String getData) async{
print('--- initialise');
dataReceived = await _convertDataReceived(getData);
myFuture = loadingInitialElementData();
}
// Functions public
// ---------------------------------------------------------------------------
Future<void> loadingInitialElementData() async
{
print('---------------------- dataReceived');
print(dataReceived); // => I see my data in the console
// ... some operations
}
}
Error
I don't understand why I've this error, what is my mistake ?
======== Exception caught by widgets library =======================================================
The following assertion was thrown building InitialElementResultScreen(dirty, dependencies: [_InheritedProviderScope<InitialElementResultNotifier>]):
Tried to use Provider with a subtype of Listenable/Stream (InitialElementResultNotifier).
This is likely a mistake, as Provider will not automatically update dependents
when InitialElementResultNotifier is updated. Instead, consider changing Provider for more specific
implementation that handles the update mechanism, such as:
- ListenableProvider
- ChangeNotifierProvider
- ValueListenableProvider
- StreamProvider
Alternatively, if you are making your own provider, consider using InheritedProvider.
If you think that this is not an error, you can disable this check by setting
Provider.debugCheckInvalidValueType to `null` in your main file: