Hello!
Met an issue with ChangeNotifierProxyProvider
Here is a snippet of a simple program
It adds 1 to a random generated number (from 1 to 10) and writes an equation in form like '5 + 1 = 6'
But Provider2 is not getting correct number from Provider1 (provider: ^4.0.2)
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
class Provider1 with ChangeNotifier {
// Generates random number from 1 to 10
int randN = 0;
void generateRandomNumber() {
randN = Random().nextInt(10);
print(randN);
notifyListeners();
}
}
class Provider2 with ChangeNotifier {
// Adds 1 to early generated number
int increasedN;
Provider2(this.increasedN);
void increaseByOne() {
increasedN = increasedN + 1;
print(increasedN);
notifyListeners();
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider.value(
value: Provider1(),
),
ChangeNotifierProxyProvider<Provider1, Provider2>(
create: null,
update: (_, prov1, __) => Provider2(prov1.randN),
),
],
child: MaterialApp(
title: 'Demo',
home: Home(),
),
);
}
}
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Demo'),
),
body: Column(
children: <Widget>[
Text(
'${Provider.of<Provider1>(context).randN} + 1 = ${Provider.of<Provider2>(context).increasedN}'),
RaisedButton(
onPressed: () {
Provider.of<Provider1>(context, listen: false)
.generateRandomNumber();
Provider.of<Provider2>(context, listen: false)
.increaseByOne(); // if remove 'listen: false' - get error
},
child: Text('Generate Random Number'),
),
],
),
);
}
}
Sorry if it's an obvious problem, but i cannot see solution and spent too much time on it already
[鉁揮 Flutter (Channel master, v1.14.7-pre.103, on Linux, locale en_US.UTF-8)
[鉁揮 Android toolchain - develop for Android devices (Android SDK version 29.0.1)
[鉁揮 Android Studio (version 3.4)
[鉁揮 VS Code (version 1.41.1)
[鉁揮 Connected device (1 available)
Hi, sorry i had no time to try your code but this might help:
MultiProvider(
providers: [
ChangeNotifierProvider(
builder: (_, __) => Provider1(),
),
ChangeNotifierProxyProvider<Provider1, Provider2>(
create: (context) => Provider2(Provider.of<Provider1>(context, listen: false).randN),
update: (_, prov1, prev) => prev..increaseByOne(prov1.randN),
),
],
void increaseByOne(int randN) {
increasedN = randN + 1;
print(increasedN);
notifyListeners();
}
@smiLLe Thanks, it worked!
But now increaseByOne() function is executing 2 times
And is there a way to not pass prov1.randN directly to increaseByOne function?
Because now there is a line
Provider.of<Provider2>(context, listen: false).increaseByOne(Provider.of<Provider1>(context, listen: false).randN);
And it looks too complicated
Whole working code is here
```import 'dart:math';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
class Provider1 with ChangeNotifier {
// Generates random number from 1 to 10
int randN = 0;
void generateRandomNumber() {
randN = Random().nextInt(10);
print(randN);
notifyListeners();
}
}
class Provider2 with ChangeNotifier {
// Adds 1 to early generated number
int increasedN;
Provider2(this.increasedN);
void increaseByOne(int randN) {
increasedN = randN + 1;
print(increasedN);
notifyListeners();
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider.value(
value: Provider1(),
),
ChangeNotifierProxyProvider
create: (context) =>
Provider2(Provider.of
update: (_, prov1, prev) => prev..increaseByOne(prov1.randN),
),
],
child: MaterialApp(
title: 'Demo',
home: Home(),
),
);
}
}
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Demo'),
),
body: Column(
children:
Text(
'${Provider.of
RaisedButton(
onPressed: () {
Provider.of
.generateRandomNumber();
Provider.of
Provider.of
.randN);
},
child: Text('Generate Random Number'),
),
],
),
);
}
}
```
Calling increment inside update without any sort of condition is a bad idea
You have to make sure that the value changed
Closing this since it seems to be solved.
Thanks, I understood what was wrong
Sorry for late response
Here is correct code if someone needs it
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
class Provider1 with ChangeNotifier {
int randN = 0;
void generateRandomNumber() {
randN = Random().nextInt(10);
notifyListeners();
}
}
class Provider2 with ChangeNotifier {
int increasedN;
void increaseByOne(int randN) {
increasedN = randN + 1;
notifyListeners();
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider.value(
value: Provider1(),
),
ChangeNotifierProxyProvider<Provider1, Provider2>(
create: (context) => Provider2(),
update: (_, prov1, prov2) => prov2..increaseByOne(prov1.randN),
),
],
child: MaterialApp(
title: 'Demo',
home: Home(),
),
);
}
}
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Demo'),
),
body: Column(
children: <Widget>[
Text(
'${Provider.of<Provider1>(context).randN} + 1 = ${Provider.of<Provider2>(context).increasedN}'),
RaisedButton(
onPressed: () {
Provider.of<Provider1>(context, listen: false)
.generateRandomNumber();
},
child: Text('Generate Random Number'),
),
],
),
);
}
}
Most helpful comment
Calling
incrementinsideupdatewithout any sort of condition is a bad ideaYou have to make sure that the value changed