Flutter Provider嵌套导航 [英] Flutter Provider nested navigation

查看:308
本文介绍了Flutter Provider嵌套导航的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在提供程序和导航方面遇到问题。

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆