Flutter - 当不在具有构建方法的类中时如何获取上下文

Wil*_*ill 5 flutter

我正在为 PaginatoredDataTable 编写代码,但是当我尝试使用 showDialog() 时我迷失了方向。我想要的是当用户按下数据表中的一行时,会出现一个对话框,其中包含该行包含的信息。我遇到的问题是对话框的上下文,因为它需要上下文,而 DataRow 类本身没有上下文。

为了识别已选择一行,您必须在 DataRow 类中使用 onSelectChanged()。在这里,我尝试调用该对话框,但我必须使用全局导航键。

class CalendarResultsDataSource extends DataTableSource {
  final List<CalendarResult> _calendarResults;
  CalendarResultsDataSource(this._calendarResults);


  @override
  DataRow getRow(int index) {
    assert(index >= 0);
    if (index >= _calendarResults.length) return null;
    final CalendarResult calendarResult = _calendarResults[index];
    return DataRow.byIndex(
        index: index,
        selected: calendarResult.selected,
        onSelectChanged: (bool value) {
          print(value);
          print(calendarResult.agency);
          Dialogs.showAuditInfo(
              navigatorKey.currentState.overlay.context, calendarResult);  //<-- this feels hacky
        },
        cells: <DataCell>[
          DataCell(Container(
              height: double.infinity,
              width: double.infinity,
              color: index.isEven
                  ? ColorDefs.colorAlternatingDark
                  : ColorDefs.colorDarkBackground,
              child: Padding(
                padding: const EdgeInsets.fromLTRB(6.0, 4.0, 4.0, 4.0),
                child: Center(
                    child: Text('${calendarResult.getDateFormatted()}',
                        style: ColorDefs.textBodyWhite15)),
              ))), etc. etc.

        ]);
Run Code Online (Sandbox Code Playgroud)

在 dataRow 类中。

因此,我在 main() 中创建了一个导航键,如下所示:

final navigatorKey = GlobalKey<NavigatorState>();

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: navigatorKey,
      home: Scaffold(body: AwesomeAppCodeHere())
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

然后,我在 onSelectChanged() 方法中引用该键,如下所示:

showDialog<void>(
      context: navigatorKey.currentState.overlay.context,
      builder: (BuildContext context) {
        return AlertDialog(
          content: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return DialogInnards();
            },
          ),
        );
      },
    );
Run Code Online (Sandbox Code Playgroud)

但是,感觉很hacky。我能想到的唯一其他解决方案是将上下文从 PaginatoredDataTable 小部件传递到 DataRow 类,但随后我必须直接修改 flutter DataRow 小部件。

那么,在没有公开上下文的情况下获取类中上下文的最佳方法是什么?

我确实看到了“get”包:可能有用... https://pub.dev/packages/get但这对于简单的东西来说不是矫枉过正吗?(但只是逃避我?)

小智 1

我正在处理同样的事情,并且找到了解决方法。\n您可以在 DataTableSource 实现类中声明 BuildContext 属性。

\n
    class EventData extends DataTableSource {\n      final BuildContext context;\n      EventData({required this.context});\n      final List<Map<String, dynamic>> _data = List.generate(\n          200,\n          (index) => {\n                "price": Random().nextInt(1000),\n              });\n    \n      @override\n      DataRow? getRow(int index) {\n        return DataRow(cells: [\n          DataCell(Center(\n            // We can know use the context in this method.\n            child: Text("${_data[index][\'price\']} \xe2\x82\xac",\n                style: Theme.of(context)\n                    .textTheme\n                    .headline6!\n                    .copyWith(fontWeight: FontWeight.bold)),\n          )),\n        ]);\n      }\n    \n      @override\n      bool get isRowCountApproximate => false;\n    \n      @override\n      int get rowCount => _data.length;\n    \n      @override\n      int get selectedRowCount => 0;\n    }\n
Run Code Online (Sandbox Code Playgroud)\n

此属性必须由您的 UI 提供,现在可以在 DataTableSource 类的方法中使用。

\n
class PaginatedExample extends StatelessWidget {\n  const PaginatedExample({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return PaginatedDataTable(\n      source: EventData(context: context), //The context can be provided here.\n      columns: const [\n        DataColumn(label: Text(\'Price\')),\n      ],\n    );\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

此解决方案的缺点是,EventData 类将在每次 UI 重建时重新实例化。

\n