是否可以有多个完全相同类型的 Riverpod ChangeNotificationProvider?
Is it possible to have multiple Riverpod ChangeNotificationProviders of the same exact type?
我已经围绕 riverpod ChangeNotificationProvider 成功构建了一个 NewsScreen
以从 REST api 轮询数据,然后创建一个列表视图。
我的应用有多个由底部标签导航控制的页面。在两个选项卡中,我想显示 NewsScreen
.
两者都很好,但问题是数据源是一样的。这意味着如果我在第一页上加载第二页的新闻列表 API,另一个选项卡也会显示更多新闻项目。
这两个页面共享同一个数据源,正如我所预料的那样。
这就是我在 NewsScreen.dart
页面顶部声明我的 Provider
的方式
final NewsProvider = ChangeNotifierProvider<NewsData>((ref) {
return NewsData();
});
所以从这个意义上说,它被两个标签页 'globally' 使用。
有什么策略可以让这两个页面独立获取数据吗?我不想使用不同的提供商重新编码这个新页面的两个版本。理想情况下,我会在选项卡中使用相同的代码调用 2 次(或更多),具体取决于用户想要多少个新闻页面选项卡
这是我的应用程序的一般结构,以防它有所帮助,但如果有人有任何关于如何执行此操作的提示,或者任何我可以阅读以弄清楚它的内容,我们将不胜感激!
main.dart
void main() {
runApp(
// Adding ProviderScope enables Riverpod for the entire project
const ProviderScope(child: MyApp()),
);
}
class MyApp extends StatelessWidget{
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: Constants.appName,
home:MainScreen()
);
}
mainscreen.dart
Standard persistent_bottom_navigation. https://pub.dev/packages/persistent_bottom_nav_bar
My code can be provided if needed, but it calls NewsScreen() from 2 of the tabs on a bottom nav bar
NewsScreen.dart
final NewsProvider = ChangeNotifierProvider<NewsData>((ref) {
return NewsData();
});
class NewsScreen extends StatefulWidget {
NewsScreen({Key? key}) : super(key: key);
@override
_NewsScreenState createState() => _NewsScreenState();
}
class _NewsScreenState extends State<NewsScreen> {
//NewsScreen({Key? key}) : super(key: key);
int _allowNextPageLoad = 1;
ScrollController _scrollController = ScrollController();
@override
void initState(){
super.initState();
/// LOAD THE DATA ONLY ON THE FIRST LOAD
context.read(NewsProvider).fetchData;
(... some scroll controller stuff ...)
@override
void dispose(){
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return
Scaffold(
appBar: AppBar(
title: Text("News",
),
body: RefreshIndicator(
onRefresh: () async {
(...)
},
child: Center(
child: Container(
child: NewsScreenConsumer(),
),
),
),
);
}
}
NewsConsumer.dart
class NewsScreenConsumer extends ConsumerWidget {
NewsScreenConsumer();
@override
Widget build(BuildContext context, ScopedReader watch)
{
/// PROVIDER SETUP
final data = watch(NewsProvider);
return Container ( ... UI using data from news provider ... );
}
}
编辑
如果我按如下方式将 NewsProvider = ChangeNotifierProvider
移动到屏幕小部件中,它就可以正常工作了:
class _NewsScreenState extends State<NewsScreen> {
final NewsProvider = ChangeNotifierProvider<NewsData>((ref) {
return NewsData();
});
...
但是出现了一个新问题,我有几个 UI 小部件依赖于来自 NewsProvider 的信息,并从 _NewsScreenState
内部调用以构建 UI(本质上是小部件在 NewsConsumer.dart
)。这些不再具有访问不再全局的 NewsProvider
的权限。我希望他们能成为某种 'child' 并理解 NewsProvider
。
现在我可以将所有这些小部件的代码物理地移动到我的 _NewsScreenState
小部件中,以便它可以访问提供程序,但它不是很优雅。有没有办法将这个 NewsProvider 作为一种局部变量,仅用于为 NewsScreen 构建 UI 的几个 'child' 小部件?
好的,根据上面 Alex Hartford 的建议,我研究了 .family
概念,我发现了一些似乎有效的东西。
我把它放在这里是因为它可以帮助那里的任何人,但也因为有人注意到我的想法中存在一些明显的缺陷:
我所做的是通过将我的全局调用更改为这个
来切换到 NewsProvider .family
final NewsProvider = ChangeNotifierProvider.family<NewsData, int>((ref, id) {
return NewsData();
});
然后在我的 class _NewsScreenState extends State<NewsScreen> {
中生成一个随机 # 作为我们将要使用的这个家庭成员的 ID
class _NewsScreenState extends State<NewsScreen> {
int _randomNumber = Random().nextInt(100);
...
现在在我需要使用我的 Provider 的地方我这样称呼它
await context.read(NewsProvider(_randomNumber)).fetchData;
它现在似乎工作得很好。我想有可能会生成两次相同的随机数,所以我会让它从 10milllion 中选择一个随机数,或者可能想出某种随机哈希生成器。我确定我的逻辑存在一些缺陷,所以我仍然在倾听更好的方法!
我已经围绕 riverpod ChangeNotificationProvider 成功构建了一个 NewsScreen
以从 REST api 轮询数据,然后创建一个列表视图。
我的应用有多个由底部标签导航控制的页面。在两个选项卡中,我想显示 NewsScreen
.
两者都很好,但问题是数据源是一样的。这意味着如果我在第一页上加载第二页的新闻列表 API,另一个选项卡也会显示更多新闻项目。
这两个页面共享同一个数据源,正如我所预料的那样。
这就是我在 NewsScreen.dart
页面顶部声明我的 Provider
的方式
final NewsProvider = ChangeNotifierProvider<NewsData>((ref) {
return NewsData();
});
所以从这个意义上说,它被两个标签页 'globally' 使用。
有什么策略可以让这两个页面独立获取数据吗?我不想使用不同的提供商重新编码这个新页面的两个版本。理想情况下,我会在选项卡中使用相同的代码调用 2 次(或更多),具体取决于用户想要多少个新闻页面选项卡
这是我的应用程序的一般结构,以防它有所帮助,但如果有人有任何关于如何执行此操作的提示,或者任何我可以阅读以弄清楚它的内容,我们将不胜感激!
main.dart
void main() {
runApp(
// Adding ProviderScope enables Riverpod for the entire project
const ProviderScope(child: MyApp()),
);
}
class MyApp extends StatelessWidget{
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: Constants.appName,
home:MainScreen()
);
}
mainscreen.dart
Standard persistent_bottom_navigation. https://pub.dev/packages/persistent_bottom_nav_bar
My code can be provided if needed, but it calls NewsScreen() from 2 of the tabs on a bottom nav bar
NewsScreen.dart
final NewsProvider = ChangeNotifierProvider<NewsData>((ref) {
return NewsData();
});
class NewsScreen extends StatefulWidget {
NewsScreen({Key? key}) : super(key: key);
@override
_NewsScreenState createState() => _NewsScreenState();
}
class _NewsScreenState extends State<NewsScreen> {
//NewsScreen({Key? key}) : super(key: key);
int _allowNextPageLoad = 1;
ScrollController _scrollController = ScrollController();
@override
void initState(){
super.initState();
/// LOAD THE DATA ONLY ON THE FIRST LOAD
context.read(NewsProvider).fetchData;
(... some scroll controller stuff ...)
@override
void dispose(){
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return
Scaffold(
appBar: AppBar(
title: Text("News",
),
body: RefreshIndicator(
onRefresh: () async {
(...)
},
child: Center(
child: Container(
child: NewsScreenConsumer(),
),
),
),
);
}
}
NewsConsumer.dart
class NewsScreenConsumer extends ConsumerWidget {
NewsScreenConsumer();
@override
Widget build(BuildContext context, ScopedReader watch)
{
/// PROVIDER SETUP
final data = watch(NewsProvider);
return Container ( ... UI using data from news provider ... );
}
}
编辑
如果我按如下方式将 NewsProvider = ChangeNotifierProvider
移动到屏幕小部件中,它就可以正常工作了:
class _NewsScreenState extends State<NewsScreen> {
final NewsProvider = ChangeNotifierProvider<NewsData>((ref) {
return NewsData();
});
...
但是出现了一个新问题,我有几个 UI 小部件依赖于来自 NewsProvider 的信息,并从 _NewsScreenState
内部调用以构建 UI(本质上是小部件在 NewsConsumer.dart
)。这些不再具有访问不再全局的 NewsProvider
的权限。我希望他们能成为某种 'child' 并理解 NewsProvider
。
现在我可以将所有这些小部件的代码物理地移动到我的 _NewsScreenState
小部件中,以便它可以访问提供程序,但它不是很优雅。有没有办法将这个 NewsProvider 作为一种局部变量,仅用于为 NewsScreen 构建 UI 的几个 'child' 小部件?
好的,根据上面 Alex Hartford 的建议,我研究了 .family
概念,我发现了一些似乎有效的东西。
我把它放在这里是因为它可以帮助那里的任何人,但也因为有人注意到我的想法中存在一些明显的缺陷:
我所做的是通过将我的全局调用更改为这个
来切换到 NewsProvider.family
final NewsProvider = ChangeNotifierProvider.family<NewsData, int>((ref, id) {
return NewsData();
});
然后在我的 class _NewsScreenState extends State<NewsScreen> {
中生成一个随机 # 作为我们将要使用的这个家庭成员的 ID
class _NewsScreenState extends State<NewsScreen> {
int _randomNumber = Random().nextInt(100);
...
现在在我需要使用我的 Provider 的地方我这样称呼它
await context.read(NewsProvider(_randomNumber)).fetchData;
它现在似乎工作得很好。我想有可能会生成两次相同的随机数,所以我会让它从 10milllion 中选择一个随机数,或者可能想出某种随机哈希生成器。我确定我的逻辑存在一些缺陷,所以我仍然在倾听更好的方法!