Closed Trung15010802 closed 3 weeks ago
It's just how TabBarView
works. The new tile is built before the old tile is removed and thus the provider is being watched the whole time.
It's just how
TabBarView
works. The new tile is built before the old tile is removed and thus the provider is being watched the whole time.import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() => runApp(const ProviderScope(child: TabBarApp()));
final countProvider = StateProvider.autoDispose
return 0; });
class TabBarApp extends StatelessWidget { const TabBarApp({super.key});
@override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData(useMaterial3: true), home: const TabBarExample(), ); } }
List
class TabBarExample extends StatefulWidget { const TabBarExample({super.key});
@override
State
class _TabBarExampleState extends State
class Tile extends ConsumerStatefulWidget { const Tile({super.key});
@override
ConsumerState
class _TileState extends ConsumerState
@override void initState() { color = randomColor(); super.initState(); }
@override void dispose() { debugPrint('Tile widget disposed'); super.dispose(); }
@override Widget build(BuildContext context) { final count = ref.watch(countProvider); return Container( color: color, alignment: Alignment.center, child: Text( count.toString(), style: const TextStyle( fontSize: 24, color: Colors.white, shadows: [ Shadow(color: Colors.black, offset: Offset(1, 1), blurRadius: 1) ], ), ), ); } }
Color randomColor() { final random = Random(); return Color.fromARGB( 255, random.nextInt(256), random.nextInt(256), random.nextInt(256), ); }
I don't use TabBarView anymore but still not work as my expectation
Try adding a print statement inside the build method and you will notice that the disposal of the old widget happens after the creation of the new widget.
Try adding a print statement inside the build method and you will notice that the disposal of the old widget happens after the creation of the new widget.
So could you show me a way to achieve my my goal, pls?
What's your use case? A simple workaround would be calling ref.invalidate
when changing tabs.
What's your use case? A simple workaround would be calling
ref.invalidate
when changing tabs.
So autoDispose have no effect in my case? And i have to dispose it manualy. I can't use ref.invalidate in dispose() method
That's expected.
The provider is there in the widget tree when you switch between tabs. To be disposed, it has to not exist in the widget tree for at least 1 frame, which doesn't happen in your case.
You can check ref.onCancel
and ref.onResume
to ensure it has correctly removed the last listener and then the provider is listened to again. Or, you can just check ref.onAddListener
and ref.onRemoveListener
.
If you need the provider to be specific to a widget, you can use family provider and pass some cached key related to the widget. In that case, both widgets will be using a different version of the same provider.
That's expected.
The provider is there in the widget tree when you switch between tabs. To be disposed, it has to not exist in the widget tree for at least 1 frame, which doesn't happen in your case.
You can check
ref.onCancel
andref.onResume
to ensure it has correctly removed the last listener and then the provider is listened to again. Or, you can just checkref.onAddListener
andref.onRemoveListener
.If you need the provider to be specific to a widget, you can use family provider and pass some cached key related to the widget. In that case, both widgets will be using a different version of the same provider.
Thank you very much. Now i understand
Describe the bug I have two screen contain the same widget and i register a listener by using ref.watch on that widget. But when move from screen1 to screen2. Widget is disposed but provider don't.
To Reproduce
Expected behavior I think the provider should be dispose after previous widget is disposed and create a new provider in the next widget