gpt4 book ai didi

flutter - 在此小部件上方找不到正确的提供者

转载 作者:IT王子 更新时间:2023-10-29 07:16:47 26 4
gpt4 key购买 nike

我在使用 Flutter Provider 时遇到问题...我的流程是这样的:登录用户 ID 传递给新的小部件后 -> 从那里预制保存到数据库,然后重定向到新的小部件(仪表板)。

这是登录后的小部件代码:

return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: ListView(
children: <Widget>[
Container(
margin: EdgeInsets.all(8.0),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8.0))),
child: InkWell(
onTap: () {
var user = Provider.of<UserRepository>(context);
user.savePreference(user.user.id, "Something");
user.navigateToNewPage(Dashboard(), context);
print(user.user.id);
},

这个有效:

user.savePreference(user.user.id, "Something");

但这引起了一个问题:

user.navigateToNewPage(Dashboard(), context);

在仪表板小部件中,我正在创建这个:

 Widget build(BuildContext context) {
var user = Provider.of<UserRepository>(context);

在 UserRepository 中我有这个:

class UserRepository with ChangeNotifier {
User user;
Status _status = Status.Uninitialized;

Status get status => _status;
User get getUser => user;

UserRepository.instance();

Future<void> navigateToNewPage(Widget page, BuildContext context) {
Navigator.push(context, MaterialPageRoute(builder: (context) => page));
}

我知道这个主题已经解决了问题,但找不到适合我问题的内容。

最佳答案

提供商范围

MaterialApp
> provider(Screen A)
> Screen B

如果 Provider 在屏幕 A 中实例化,则在从 A → B 执行 Navigator.push 后将无法在屏幕 B 中访问它。

为什么?

因为 Provider 是一个 InheritedWidgetNavigator 在其 Screen A context< 之外使用 MaterialApp context/范围。 (请参阅下面的详细信息。)

修复

Provider 移动到一个共同的父级 MaterialApp 上下文,允许屏幕 A 和 B 继承其状态/上下文。

provider(MaterialApp)
> Screen A
> Screen B

示例

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
/// wrap MaterialApp in Provider widget
return ChangeNotifierProvider(
create: (context) => ColorModel(), // ← create/init your state model
child: MaterialApp(
home: ScreenA()
),
);
}
}

详情

供应商

  • Provider 基于 InheritedWidget。只有 小部件可以继承 父小部件的状态。

    • Provider 需要成为任何想要访问“提供的”状态对象的小部件树的根小部件

导航器

    屏幕 A 上的
  • Navigator.push(context) 不使用屏幕 A 中的 context
    • 它使用 MaterialApp 中的 context
  • Navigator.push(context)其实就是Navigator.of(context).push
  • Navigator.of(context) 表示:搜索此上下文层次结构,直到找到实例化 Navigator 的上下文
    • 默认的 NavigatorMaterialApp 中实例化。
    • 除非您明确创建/使用不同的 Navigator,否则您使用的是默认值。
    • NavigatorcontextMaterialApp 的。
  • 屏幕 B 将获取那个上下文(MaterialApp),不是屏幕 A 的上下文。
    • B 是 A 的兄弟,而不是它的 child 。
    • B 不继承自 A,即使它在 context A 中出现“实例化”。
    • 屏幕 B 是 MaterialApp context,而不是屏幕 A context
    • Provider context 范围,如果在屏幕 A 中定义,则不会覆盖屏幕 B

屏幕 A → B

Navigator.push(context, MaterialPageRoute(builder: (context) => ScreenB()))

实际上是:

Navigator.of(context).push(MaterialPageRoute(builder: (context) => ScreenB()))

这就像:

Navigator.of(MaterialApp).push(
MaterialPageRoute(builder: (MaterialAppContext) => ScreenB())
)

所以屏幕 B 在 MaterialApp context 下,在屏幕 A context 下,因此无法访问屏幕 A Provider 及其 context

参见 this answer for a code sample关于 Provider 的类似问题。

关于flutter - 在此小部件上方找不到正确的提供者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57124258/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com