使用命名路由导航时找不到流提供程序

Posted

技术标签:

【中文标题】使用命名路由导航时找不到流提供程序【英文标题】:Can't find the stream provider when using named route navigation 【发布时间】:2020-09-13 17:18:55 【问题描述】:

我有一个无法正常工作的流提供程序(连接到 firebase)。我猜问题在于我使用的是命名导航器 [Navigator.pushNamed(context, '/route',)]。我想这使得“路线”小部件不是调用它的小部件的儿子。让我在下面更好地展示它。

我的应用结构如下: 我的 ma​​in widget 处理路由并通过用户身份验证接收 Stream(这里没有问题):

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

class MyApp extends StatelessWidget 

  @override
  Widget build(BuildContext context) 
    return StreamProvider<User>.value(
      value: AuthService().user,
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Wrapper(),
        routes: 
          '/home': (context) => Wrapper(),
          '/edit_profile': (context) => UserProfile() //This is where I am having trouble.
        
      ),
    );
  

Wrapper 验证用户是否已通过身份验证并采取相应措施:

class Wrapper extends StatelessWidget 
  @override
  Widget build(BuildContext context) 

    final user = Provider.of<User>(context);

    // return either the Home or Authenticate widget
    if (user == null)
      return Authenticate();
     else 
      return HomeWrapper();
    

  

HomeWrapper 接收第二个流并重定向到我遇到问题的小部件:

class HomeWrapper extends StatefulWidget 
  @override
  _HomeWrapperState createState() => _HomeWrapperState();


class _HomeWrapperState extends State<HomeWrapper> 

  String currentBodyName = 'home';
  Widget currentBodyWidget = Home();

  @override
  Widget build(BuildContext context) 

    Widget _drawerOptions = Row(
      children: [
        FlatButton(child: someChild, onPressed: () Navigator.pushNamed(context, '/edit_profile',);,), //This is the actual call to the navigator.
      ],
    );

    return StreamProvider<Map>.value( //This is the problematic Stream!
        value: DatabaseService().userDetail,
        child: Scaffold(
        //Body
        body: currentBodyWidget,

        //I am simplifying this to show the most important parts
        bottomNavigationBar: myBottomNavigationBar(
          buttons: <Widget>[
            FlatButton(
              icon: someIcon,
              onPressed: () =>  _onItemTapped('home'),
            ),
            FlatButton(
              icon: otherIcon,
              onPressed: () => _onItemTapped('second_screen'),
            ),
          ],)

          //Drawer
          drawer: Drawer(child: _drawerOptions,), //This one has the call to the problematic edit_profile route.
    );
  

  void _onItemTapped(String newBodyName) 
    if (newBodyName != currentBodyName)
      setState(() 
        currentBodyName = newBodyName;
        switch(newBodyName) 
          case 'home': 
            currentBodyWidget = Home();
          
          break;

          case 'second_screen': 
            currentBodyWidget = SecondScreen();
          
          break;

          default: 
            currentBodyWidget = Home();
          
          break;
        
      );
    
  



最后,edit_profile 路由调用 UserProfile Widget,如下所示:

class UserProfile extends StatefulWidget 
  @override
  _UserProfileState createState() => _UserProfileState();


class _UserProfileState extends State<UserProfile> 

  @override
  Widget build(BuildContext context) 

    //This is where the error occurs!!
    final userDocument = Provider.of<Map>(context) ?? [];
    print(userDocument);

    return Scaffold(body: Container());
  


这是它抛出的错误:

The following ProviderNotFoundError was thrown building UserProfile(dirty, state: _UserProfileState#09125):
Error: Could not find the correct Provider<Map<dynamic, dynamic>> above this UserProfile Widget

非常感谢!!

【问题讨论】:

【参考方案1】:

原来我的方法是错误的。

我没有用 StreamProvider 包装 HomeWrapper,希望它将数据传递到下一个路由(UserProfile),我所做的是用 StreamProvider 包装 UserProfile 小部件,如下所示:

(注意:我将 Map StreamProvider 更改为 UserData StreamProvider。)

class UserProfile extends StatefulWidget 
  @override
  _UserProfileState createState() => _UserProfileState();


class _UserProfileState extends State<UserProfile> 

  @override
  Widget build(BuildContext context) 
    final user = Provider.of<User>(context);

    return StreamBuilder<UserData>(
        stream: DatabaseService(uid: user.uid).userData,
        builder: (context, snapshot) 
          if (snapshot.hasData) 
            UserData userData = snapshot.data;

            return Scaffold(
              body: Container(
                   //My Widget here
            );
           else
            return Loading();
        );
  

这个系列非常有帮助:https://www.youtube.com/playlist?list=PL4cUxeGkcC9j--TKIdkb3ISfRbJeJYQwC

【讨论】:

以上是关于使用命名路由导航时找不到流提供程序的主要内容,如果未能解决你的问题,请参考以下文章

在使用模块 xlsx 样式时找不到命名空间 XLSX

使用 Laravel 路由时找不到 404 错误

在 Ionic 2 中使用 NodeJS.Timer 时找不到命名空间 NodeJS

尝试使用导航器页面访问时找不到 Flutter scoped_model

使用反应创建上下文时找不到命名空间“ctx”错误 - 打字稿

登录时找不到“GET /”Symfony 的路由