Flutter Provider嵌套导航 [英] Flutter Provider nested navigation
问题描述
我在提供程序和导航方面遇到问题。
I have a problem with provider and navigation.
我有一个带有对象列表的 HomeScreen
。当您单击一个对象时,我使用标签导航导航到 DetailScreen
。该 DetailScreen
用ChangenotifierProvider包装,该提供程序提供了 ViewModel
I have a HomeScreen
with a list of objects. When you click on one object I navigate to a DetailScreen
with tab navigation. This DetailScreen
is wrapped with a ChangenotifierProvider which provides a ViewModel
现在,当我使用 Navigator.of(context).push(EditScreen)
导航到另一个屏幕时,我无法访问 ViewModel
EditScreen
中的code>引发以下错误
Now, when I navigate to another screen with Navigator.of(context).push(EditScreen)
I can't access the ViewModel
within the EditScreen
The following error is thrown
════════ Exception caught by gesture ═══════════════════════════════════════════
The following ProviderNotFoundException was thrown while handling a gesture:
Error: Could not find the correct Provider<ViewModel> above this EditScreen Widget
这是我要实现的目标的简单概述
This is a simple overview of what I try to achieve
Home Screen
- Detail Screen (wrapped with ChangeNotifierProvider)
- Edit Screen
- access provider from here
我知道问题出在哪里。我正在堆栈上推一个新屏幕,并且更改通知器不再可用。
我考虑过要在我的应用程序顶部创建一个详细信息存储库,其中包含DetailView的所有ViewModel。
I know what the problem is. I'm pushing a new screen on the stack and the change notifier is not available anymore. I thought about creating a Detail Repository on top of my App which holds all of the ViewModels for the DetailView.
我知道我可以将ChangeNotifier包裹在我的MaterialApp周围,但是我不想要那样,或者因为我不知道哪个Detail-ViewModel而不能这样做我需要。我想要列表中的每个项目都使用ViewModel
I know I could wrap the ChangeNotifier around my MaterialApp, but I don't want that, or can't do it because I don't know which Detail-ViewModel I need. I want a ViewModel for every item in the list
我真的不知道什么是解决此问题的最佳方法。谢谢大家的帮助
I really don't know what's the best way to solve this. Thanks everyone for the help
这是一个快速的示例应用程序:
Here is a quick example app:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton(
child: Text("DetailView"),
onPressed: () => Navigator.of(context).push(MaterialPageRoute(
builder: (context) => ChangeNotifierProvider(
create: (_) => ViewModel(), child: DetailScreen()))),
)));
}
}
class DetailScreen extends StatelessWidget {
const DetailScreen({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton(
child: Text("EditScreen"),
onPressed: () => Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => EditScreen())),
),
));
}
}
class EditScreen extends StatelessWidget {
const EditScreen({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton(
child: Text("Print"),
onPressed: () =>
Provider.of<ViewModel>(context, listen: false).printNumber()),
),
);
}
}
class ViewModel extends ChangeNotifier {
printNumber() {
print(2);
}
}
推荐答案
到为了能够跨导航访问提供程序,您需要在MaterialApp之前提供它,如下所示:
To be able to access providers accross navigations, you need to provide it before MaterialApp as follows
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => ViewModel(),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton(
child: Text("DetailView"),
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => DetailScreen(),
),
),
)));
}
}
class DetailScreen extends StatelessWidget {
const DetailScreen({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton(
child: Text("EditScreen"),
onPressed: () => Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => EditScreen())),
),
));
}
}
class EditScreen extends StatelessWidget {
const EditScreen({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton(
child: Text("Print"),
onPressed: () =>
Provider.of<ViewModel>(context, listen: false).printNumber()),
),
);
}
}
class ViewModel extends ChangeNotifier {
printNumber() {
print(2);
}
}
这篇关于Flutter Provider嵌套导航的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!