如何在Flutter中从第三页调用第一页的功能?

时间:2018-12-23 05:38:25

标签: dart flutter

我基本上需要从另一个页面调用一个函数。这是我的导航结构:1st Screen> 2nd Screen> 3rd Screen。

我已经阅读了许多有关我的问题的主题,但是我还没有找到完美的答案。我尝试使用ScopedModelInheritedWidgets,但是它需要树上的小部件才能传递数据。

我正在使用具有pushNamed()功能的导航器的命名路由来推送这些页面。

比方说,我的第一个屏幕具有一个列表视图和一个刷新它的功能:void refresh()。如何直接从第三屏幕调用refresh()函数?

2 个答案:

答案 0 :(得分:1)

您可以通过多种方式执行此操作 一些常见的方法是

  1. 通过构造函数向下传递函数并调用
  2. 使用rxDart
  3. 使用scoped_model或任何状态管理库

答案 1 :(得分:0)

我已经找到了完美的解决方案。我必须使用scoped_model包,创建一个要用作ListView数据源的模型,并且如果我尝试更改模型的值,它应该在应用程序中的任何位置自动更新。而无需使用ScopedModelDescendant小部件的静态方法是调用此ScopedModel.of<MyModel>(context, rebuildOnChange: true).refresh();

model.dart文件

class DataModel extends Model {
  bool _loading = false;

  String _data = "";

  bool get loading => _loading;
  String get data => _data;

  void refresh() {
    this._loading = true;
    print("loading...");
    notifyListeners();

    String url = "https://reqres.in/api/users/2?delay=1";
    http.get(url).then((response) {
      _loading = false;
      print("refreshed data: ${response.body}");
      this._data = response.body;
      notifyListeners();
    });
  }

  static DataModel of(BuildContext context) =>
      ScopedModel.of<DataModel>(context);
}

main.dart文件

void main() => runApp(MyApp(model: DataModel()));

class MyApp extends StatelessWidget {
  final DataModel model;
  const MyApp({Key key, @required this.model}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ScopedModel<DataModel>(
      model: model,
      child: MaterialApp(
        title: 'ScopedModel Demo',
        routes: {
          '/': (_) => MyHomePage(title: 'Home Page'),
          '/settings': (_) => SettingsPage(),
        },
      ),
    );
  }
}

home.dart文件

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

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

class _MyHomePageState extends State<MyHomePage> {

  @override
    void initState() {
      // I can fetch new data here statically without the use of the ScopedModelDescendant in the widget tree.
      DataModel.of(context).refresh();
      super.initState();
    }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ScopedModelDescendant<DataModel>(
        builder: (context, child, model) {
          return Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(model.loading ? "LOADING..." : ""),
                Text("data: ${model.data}"),
                // Statically reading the value from the model
                RaisedButton(child: Text("Read value statically"), onPressed: () {
                  String value = DataModel.of(context).data;
                  print("$value");
                },),
                RaisedButton(child: Text("Settings"), onPressed: () {
                  Navigator.pushNamed(context, "/settings");
                },)
              ],
            ),
          );
        },
      ),
      floatingActionButton: ScopedModelDescendant<DataModel>(
        builder: (context, child, model) {
          return FloatingActionButton(
            child: Icon(Icons.refresh),
            onPressed: () {
              // here is the ScopedModelDescendant version of refreshing data
              model.refresh();
            },
          );
        },
      ),
    );
  }
}