一尘不染

如何将继承的小部件传递到整个Material App

flutter

所以我有一个继承的小部件,看起来像:

class InheritedStateWidget extends StatefulWidget {
  final Widget child;

  InheritedStateWidget({
    @required this.child
  });

  @override
  InheritedStateWidgetState createState() => new InheritedStateWidgetState();

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

class InheritedStateWidgetState extends State<InheritedStateWidget> {
  String _userName;

  // Getter methods
  String get tasks => _userName;

  void changeUserName(String name) {
    setState(() {
      _userName = name;      
    });
  }
  @override
  Widget build(BuildContext context) {
    return new _MyInheritedWidget(
      data: this,
      child: widget.child,
    );
  }

}

class _MyInheritedWidget extends InheritedWidget {
  final InheritedStateWidgetState data;

  _MyInheritedWidget({
    Key key,
    this.data,
    Widget child}): super(key: key, child: child);

    @override
    bool updateShouldNotify(_MyInheritedWidget old) {
      return true;
    }
}

和这样的main.dart:

void main() => runApp(InheritedStateWidget(
  child: new Builder ( builder: (context) => new MyApp()))
  );

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'App One',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(),
    );
  }
}

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

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

class _MyHomePageState extends State<MyHomePage> {
  final PageStorageBucket bucket = PageStorageBucket();

  int currentTab;
  Widget currentPage;
  List<Widget> pages;
  HomePage one;
  ProfilePage two;

  @override
  void initState() {
    super.initState();
    one = HomePage(
      key: exploreKey,
    );
    two = Profile(
      key: myTasksKey,
    );

    pages = [one, two];

    currentPage = one;
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(title: new Text("Testing"),),
      body: new PageStorage(
        bucket: bucket,
        child: currentPage,
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: currentTab,
        onTap: (int index) {
          setState(() {
            currentTab = index;
            currentPage = pages[index];
          });
        },
        type: BottomNavigationBarType.fixed,
        items: <BottomNavigationBarItem> [
          BottomNavigationBarItem(
            title: Text("Home"),
            icon: null
          ),
          BottomNavigationBarItem(
            title: Text("Profile"),
            icon: null
          )
        ],
      )
    );
  }
}

从我从一些指南中获得的信息,这就是我应该如何将继承的小部件传递到我的Material
App及其所有路线,但是它似乎并没有将继承的小部件传递通过支架。从脚手架本身看来,我能够做类似的事情:

InheritedStateWidget.of(上下文)

它会成功地带回我的Inherited Widget,但是在currentPage Widget中,即HomePage(Stateful
Widget)。我似乎无法访问它,我得到了

未处理的异常:NoSuchMethodError:类’HomePageState’没有实例获取方法’InheritedStateWidget’。接收方:“
HomePageState”的实例

我要去哪里错了?


阅读 226

收藏
2020-08-13

共1个答案

一尘不染

我对您的前几节课进行了稍微的重组:

import 'package:flutter/material.dart';

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

class InheritedStateWidget extends StatefulWidget {
  @override
  InheritedStateWidgetState createState() => InheritedStateWidgetState();
}

class InheritedStateWidgetState extends State<InheritedStateWidget> {
  String _userName;

  // Getter methods
  String get tasks => _userName;

  void changeUserName(String name) {
    setState(() {
      _userName = name;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new MyInheritedWidget(
      data: this,
      child: MyApp(),
    );
  }
}

class MyInheritedWidget extends InheritedWidget {
  final InheritedStateWidgetState data;

  MyInheritedWidget({Key key, this.data, Widget child})
      : super(key: key, child: child);

  static MyInheritedWidget of(BuildContext context) =>
      context.inheritFromWidgetOfExactType(MyInheritedWidget);

  @override
  bool updateShouldNotify(MyInheritedWidget old) => true;
}

class MyApp extends StatelessWidget {
  // in MyApp and below you can refer to MyInheritedWidget.of(context).data
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'App One',
      home: new MyHomePage(),
    );
  }
}

我喜欢像这样加强State和InheritedWidget之间的接口,但这只是一个建议…

void main() => runApp(new Controller());

class Controller extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => ControllerState();
}

typedef void VoidIntFunction(int i);

class ControllerState extends State<Controller> {
  String someString = '';

  void someFunction(int v) {
    print('function called with $v');
  }

  @override
  Widget build(BuildContext context) {
    return StateContainer(
      someString: someString,
      someFunction: someFunction,
      child: new ExampleApp(),
    );
  }
}

class StateContainer extends InheritedWidget {
  final String someString;
  final VoidIntFunction someFunction;

  const StateContainer({
    this.someString,
    this.someFunction,
    Widget child,
  }) : super(child: child);

  static StateContainer of(BuildContext context) =>
      context.inheritFromWidgetOfExactType(StateContainer);

  @override
  bool updateShouldNotify(StateContainer oldWidget) => true;
}

现在使用InheritedWidget的任何子级都具有对状态(someString)的读取权限,并且必须通过调用方法(someFunction)对其进行修改。涉及更多样板。

2020-08-13