首页 > 解决方案 > 如何将继承的小部件传递给整个 Material 应用程序

问题描述

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

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(context)

它会成功带回我的继承小部件,但在当前页面小部件中,即主页(有状态小部件)。我似乎无法访问它,我得到了

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

我哪里错了?

标签: flutter

解决方案


我稍微重组了你的前几类:

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) 来修改它。涉及更多样板。


推荐阅读