Как использовать InheritedWidget в составе моего приложения - PullRequest
0 голосов
/ 06 мая 2020

Я новичок в фреймворке унаследованных виджетов во флаттере. Мне удалось заставить его работать, но только путем обертывания всего MaterialApp в ModelContainer. Есть ли способ реализовать это только для части моего приложения? (Я не хочу, чтобы данные были доступны во всем приложении, только в разделе, поддереве).

Структура моего приложения примерно следующая:

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return myModelContainer( //<--- This is what I would like to move
        initialModel: myModel(),
        child: MaterialApp(
          debugShowCheckedModeBanner: false,
          title: "myApp",

          home: Wrapper(),
          initialRoute: '/',
          routes: {
            '/home': (context) => Wrapper(),
            '/mySubsection': (context) => Subsection(),
          }
        ),
      ),
    );
  }
}

I хотел бы реализовать унаследованный виджет только в этом подразделе. Подраздел выглядит так:

class Subsection extends StatefulWidget {

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

class _SubsectionState extends State<Subsection> {

  @override
  Widget build(BuildContext context) {

    return Scaffold( //If I placed the model container here it doesn't work. 'Getter Data was called on null'
        appBar: AppBar(
          title: Text('SomeText'),
        ),
        body: Container(
          child: ListView(
            children: <Widget>[
              SizedBox(height: 10,),
              _SonWidget1(),
              SizedBox(height: 12,),
            ],
          ),
        ));
  }
}

class _SonWidget1 extends StatelessWidget {

  @override
  Widget build(BuildContext context) {

    void _showPanel() {
      showModalBottomSheet(
          context: context,
          isScrollControlled: true,
          builder: (BuildContext bc) {
            return Wrap(
              children: <Widget>[
                Container(
                  child: sonWidget2(), //<--- Eventually I would like to use the data in this son widget.
              ),
            ]);
          });

    }

    return Column(
      children: <Widget>[
        flatButton(
                  onPressed: _showPanel,
                ),
      ],
    );
  }
}

Наконец, моя реализация унаследованного виджета выглядит так:

class ModelContainer extends StatefulWidget {
  final Widget child;
  final Model initialModel;

  ModelContainer(
      {@required this.child, @required this.initialModel}
      ): assert(initialModel != null);


  static ModelContainerState of(BuildContext context){
    return(context.inheritFromWidgetOfExactType(InheritedContainer) as InheritedContainer).data;
  }

  ModelContainerState createState() => ModelContainerState();
}

class ModelContainerState extends State<ModelContainer> {
  Model myModel;

  @override
  void initState() {
    super.initState();
    myModel = widget.initialModel;
  }

  void updateModel(){
    if(myModel==null){
      setState(() {
        myModel=new Model();
      });
    }
    else{
      setState(() {
        //Some update logic
      });
    }

  }

  @override
  Widget build(BuildContext context) {
    return InheritedContainer(
      data:this,
      child: widget.child,
    );
  }
}

class InheritedContainer extends InheritedWidget {
  final ModelContainerState data;

  InheritedContainer({Key key,@required this.data, @required Widget child}) : super(key: key, child: child);

  @override
  bool updateShouldNotify( InheritedContainer oldWidget) {
    return true;
  }
}

Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...