Describe the bug
When creating a StreamProvider with a value of Stream.value(null) and then override it in another page then this should only be null until it is set. Right now it seems like it resets when navigating with an animation.
Have added a deugPrint(user.name) to easily see the behavior in the console.
To Reproduce
Click the ListTile and look at the log.
class User {
String id;
String name;
User.empty() {
id = "";
name = "";
}
User.other() {
id = "12345";
name = "Tester";
}
@override
bool operator ==(Object other) => identical(this, other) || other is User && runtimeType == other.runtimeType && name == other.name;
@override
int get hashCode => name.hashCode;
}
final userProvider = StreamProvider<User>((ref) {
return Stream.value(User.empty());
});
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ProviderScope(
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: PageOne(),
),
);
}
}
class PageOne extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ProviderScope(
// This override is causing the issue.
// If this override would be at the material app
// then the debugPrint will always print Tester
overrides: [
userProvider.overrideAs(
StreamProvider(
(ref) => Stream.value(User.other()),
),
),
],
child: Scaffold(
body: OpenContainer(
closedElevation: 4,
closedBuilder: (BuildContext context, VoidCallback openContainer) {
return Consumer((context, read) {
final user = read(userProvider).data == null ? User.empty() : read(userProvider).data.value;
debugPrint(user.name);
return Container(
height: 100,
child: ListTile(
title: Text(user.name),
),
);
});
},
openBuilder: (context, __) {
return Scaffold();
},
),
),
);
}
}
Do not forget to add dependencies in .yaml
animations: ^1.1.0
flutter_riverpod: ^0.1.0
Expected behavior
When running this the debugPrint(user.name) should not be empty during navigation.
Oh, I know
It's the good-old "a provider is scoped to its route"
By using ProviderScope inside a route, the override is not accessible to other routes.
In your case, this happens not because of navigation, but because of Overlay
During the transition, your Consumer is rendered above PageOne for a moment.
Ohh I see but then what would be a good solution for that? As that value is used by both and I can not put it above the MaterialApp as let's say I have no access to the value there. (Getting the user after sign in).
It feels weird to wrap both the ClosedBuilder return value and the OpenBuilder return value with a override
Honestly, this is more of an issue with Overlay than riverpod. https://github.com/flutter/flutter/issues/36220 should be fixed.
Ideally by merging https://github.com/flutter/flutter/pull/39104
As for how to fix it... Maybe consume the value above the OpenContainer and re-override ProviderScope inside the builder with the true value
Yeah did that and it works, thanks for the help!
Honestly, this is more of an issue with Overlay than riverpod. flutter/flutter#36220 should be fixed.
Ideally by merging flutter/flutter#39104As for how to fix it... Maybe consume the value above the
OpenContainerand re-overrideProviderScopeinside the builder with the true value
Hi, I'm trying to implement this solution, however I'm getting this error:
Unsupported operation: ProviderScope was rebuilt with a different ProviderScope ancestor.
along with:
โโโโโโโโ Exception caught by widgets library โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Updated the list of overrides with providers that were not overriden before
'package:riverpod/src/framework/container.dart':
Failed assertion: line 247 pos 9: 'unusedOverrides.isEmpty'
final Widget closedScreen;
@override
Widget build(BuildContext context) {
return Consumer((context, watch) {
final bool favorited = watch(favoritedProvider);
return OpenContainer(
closedBuilder: (_, __) {
return ProviderScope(
overrides: [
favoritedProvider.overrideWithValue(favorited),
],
child: closedScreen,
);
},
openBuilder: (_, __) {
return Container();
},
);
});
md5-7a91152789ec394bd2bd3dd83b13bf86
flutter_riverpod: ^0.6.1
animations: ^1.1.2
Most helpful comment
Oh, I know
It's the good-old "a provider is scoped to its route"
By using ProviderScope inside a route, the override is not accessible to other routes.