在带有导航流的Flutter中,此Y小部件上方找不到正确的Provider <X>

时间:2019-10-22 07:45:34

标签: flutter dart flutter-provider

我不明白为什么提供商在这里不被接受。

我的main.dart看起来像这样。

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ChangeNotifierProvider<ContentDS>(
        builder: (_) => ContentDS(),
        child: Content(),
      )
    );
  }
}

Provider在Content Class中完美工作。 现在,我使用此代码将内容从“内容”转移到“内容详细信息”

Navigator.of(ctx).push(MaterialPageRoute(
                builder: (context) =>
                    ContentDetails(viewedList: listElement),
              ))

在“内容详细信息”中,我只是尝试再次访问提供者

 final ds = Provider.of<ContentDS>(context);

但这给了我以下错误

错误:在此ContentDetails小部件上方找不到正确的提供程序

  

要修复,请:

     
      
  • 确保提供者是此的始祖   ContentDetails小部件*向提供者提供类型*   向消费者提供类型*向消费者提供类型   Provider.of()*始终使用包导入。例如:import 'package:my_app/my_code.dart'; * Ensure the correct context`是   被使用。
  •   

内容详细信息代码

class ContentDetails extends StatefulWidget {
  ToDoList viewedList;

  ContentDetails({this.viewedList});

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

class _ContentDetailsState extends State<ContentDetails> with SingleTickerProviderStateMixin{

  bool isOpened = false;
  AnimationController _animationController;
  Animation<Color> _buttonColor;
  Animation<double> _animateIcon;
  Animation<double> _translateButton;
  Curve _curve = Curves.easeOut;
  double _fabHeight = 56.0;

  initState() {
    _animationController =
    AnimationController(vsync: this, duration: Duration(milliseconds: 500))
      ..addListener(() {
        setState(() {});
      });
    _animateIcon =
        Tween<double>(begin: 0.0, end: 1.0).animate(_animationController);
    _buttonColor = ColorTween(
      begin: Colors.blue,
      end: Colors.red,
    ).animate(CurvedAnimation(
      parent: _animationController,
      curve: Interval(
        0.00,
        1.00,
        curve: Curves.linear,
      ),
    ));
    _translateButton = Tween<double>(
      begin: _fabHeight,
      end: -14.0,
    ).animate(CurvedAnimation(
      parent: _animationController,
      curve: Interval(
        0.0,
        0.75,
        curve: _curve,
      ),
    ));
    super.initState();
  }

  @override
  dispose() {
    _animationController.dispose();
    super.dispose();
  }

  animate() {
    if (!isOpened) {
      _animationController.forward();
    } else {
      _animationController.reverse();
    }
    isOpened = !isOpened;
  }

  @override
  Widget build(BuildContext context) {
    final ds = Provider.of<ContentDS>(context);

    print(" ds.count ---> " + ds.count.toString());
    if (widget.viewedList != null){
      debugPrint(" widget.viewedList.primaryID ---> " + widget.viewedList.primaryID);
    }else{
      debugPrint(" It is null");
    }
    return
     Hero(
        tag: (widget.viewedList != null) ? widget.viewedList.primaryID : 'Hero',
        child: Scaffold(
          appBar: new AppBar(
            backgroundColor: ListStatusHelper.getBgGenericColor(widget.viewedList?.status ?? ListStatus.NONE),
            title: Text('${getListTitle()}'),
            elevation: 0.0,
          ),
          floatingActionButton:  Wrap(
            direction: Axis.vertical,
            children: <Widget>[
              transformWorks(edit(), 3),
              transformWorks(save(), 2),
              transformWorks(inbox(),1),
              toggleButton()
            ],
          ),
          body: Container(
              color: ListStatusHelper.getBgGenericColor(widget.viewedList?.status ?? ListStatus.NONE),
              child: const Text("Once Provider is available, need to work on this section");

            ),
          ),
    );
  }

  Widget transformWorks(Widget btn, int pos){
    return Transform(
      transform: Matrix4.translationValues(
        0.0,
        _translateButton.value * pos,
        0.0,
      ),
      child: btn,
    );
  }

  Widget inbox() {
    return Container(
      child: FloatingActionButton(
        heroTag: null,
        onPressed: null,
        tooltip: 'Inbox',
        elevation: 0.0,
        child: Icon(Icons.inbox),
      ),
    );
  }

  Widget edit() {
    return Container(
      child: FloatingActionButton(
        heroTag: null,
        onPressed: null,
        tooltip: 'Edit',
        elevation: 0.0,
        child: Icon(Icons.edit),
      ),
    );
  }

  Widget save() {
    return Container(
      child: FloatingActionButton(
        heroTag: null,
        onPressed: null,
        tooltip: 'Save',
        elevation: 0.0,
        child: Icon(Icons.save),
      ),
    );
  }

  Widget toggleButton(){
    return  FloatingActionButton(
      heroTag: null,
      backgroundColor: _buttonColor.value,
      onPressed: animate,
      tooltip: 'Toggle',

      child: AnimatedIcon(
        icon: AnimatedIcons.menu_close,
        progress: _animateIcon,
      ),
    );
  }

  String getListTitle() {
    if (widget.viewedList != null) {
      return widget.viewedList.listTitle;
    } else {
      return 'New List';
    }
  }
}

我是一位试图学习抖动的iOS开发人员,我认为Provider应该可用于导航流程中的所有类,而无需使用任何DI。

帮助我意识到我在想什么。在诸如上述情况的导航流程中,应如何使用Provider。

预先感谢

2 个答案:

答案 0 :(得分:2)

使用Navigator.of(context)执行导航时,您推送的路线会通过其内部默认值MaterialApp成为Navigator小部件树的一部分。但是,该路由不是ChangeNotifierProvider的子代,而是MaterialApp的子代。

您应将提供商设为MaterialApp的祖先。

答案 1 :(得分:0)

ChangeNotifier移到MyApp上方:

void main() {
  runApp(ChangeNotifierProvider(
      builder: (context) => ContentDS(),
      child: MyApp()));
}