无法在新页面路由Widget中访问Provider

Unable to access Provider in new page route Widget

我无法访问我推送到当前导航器的小部件中的提供程序:

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:provider/provider.dart';


void main() => runApp(MyApp());

class MyModel with ChangeNotifier {
  String a = 'Test1';
  String b = 'Test2';
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {    

    return MaterialApp(
        title: 'Flutter Demo',
        home: ChangeNotifierProvider(
            create: (context) => MyModel(),
            child: MyHomePage()
        )
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {    

    return Consumer<MyModel>(
        builder: (context, myModel, child) =>
            Scaffold(
              appBar: AppBar(
                title: Text(myModel.a),
              ),
              floatingActionButton: FloatingActionButton(
                onPressed: () =>
                    Navigator.of(context).push(
                        PageRouteBuilder(
                            pageBuilder: (context, animation, secondaryAnimation) => Page2(),
                        ),
                    ),
                tooltip: 'Press',
                child: Icon(Icons.add),
              ),
            )
    );
  }
}

class Page2 extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    var myModel = Provider.of<MyModel>(context); // A

    return Scaffold(
              appBar: AppBar(
                title: Text(myModel.b),
              ),
            );
  }
}

我收到这个错误:

The following ProviderNotFoundException was thrown building Page2(dirty):
Error: Could not find the correct Provider<MyModel> above this Navigator Widget

问题似乎是 Page2 小部件中的 BuildContext 对象与与 Provider 关联的 BuildContext 不同。如果我将原始上下文的引用传递给 Page2 并在 (A) 点使用它,一切正常,但这似乎不是解决此问题的好方法。

我尝试了解决方案 ,方法是使用 Navigator.of(context, rootNavigator: true).context 作为 Page2 的 build 方法中的上下文,但我仍然遇到相同的异常。

你必须在根小部件中传递提供程序,这样当你导航到另一个页面时你可以从任何地方访问模型不可用所以你必须将提供程序传递给 MaterialApp 的父级

 import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:provider/provider.dart';

void main() => runApp(MyApp());

class MyModel with ChangeNotifier {
  String a = 'Test1';
  String b = 'Test2';
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => MyModel(),
      child: MaterialApp(title: 'Flutter Demo', home: MyHomePage()),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Consumer<MyModel>(
        builder: (context2, myModel, child) => Scaffold(
              appBar: AppBar(
                title: Text(myModel.a),
              ),
              floatingActionButton: FloatingActionButton(
                onPressed: () => Navigator.of(context).push(
                  PageRouteBuilder(
                    pageBuilder: (context, animation, secondaryAnimation) =>
                        Page2(),
                  ),
                ),
                tooltip: 'Press',
                child: Icon(Icons.add),
              ),
            ));
  }
}

class Page2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var myModel = Provider.of<MyModel>(context); // A

    return Scaffold(
      appBar: AppBar(
        title: Text(myModel.b),
      ),
    );
  }
}

您需要将模型传递给下一个路由,因为默认情况下提供程序的范围是路由

喜欢:

Navigator.push(
      context,
      MaterialPageRoute(
        builder: (newcontext) => 
            ChangeNotifierProvider<YourModel>.value(
                value: Provider.of<YourModel>(context),
                child: newView,
              )
      ),
    );