如何关闭带有陈旧上下文的 SearchDelegate?

Rai*_*ege 5 flutter

我已经为我的位置搜索委托构建了一个建议列表,它总是在顶部有一个项目,可以将用户推送到新页面。在这个新页面上,用户可以选择地图上的位置并提交或返回搜索页面。如果用户提交位置,我想关闭带有所选位置的基础位置搜索委托作为结果。

对于这种行为,我在无状态建议列表小部件中使用回调,但在 onMapTapped 回调的情况下,应用程序会引发异常:

class LocationSearchDelegate extends SearchDelegate<Location> {
  // ...
  @override
  Widget buildSuggestions(BuildContext context) {
    return _SuggestionList(
      query: query,
      onSelected: (Location suggestion) {
        result = suggestion;
        close(context, result);
      },
      onMapTapped: (Location location) {
        result = location;
        close(context, result); // <- Throws exception
      },
    );
  }
  // ...
}
Run Code Online (Sandbox Code Playgroud)

例外:

Looking up a deactivated widget's ancestor is unsafe.
At this point the state of the widget's element tree is no longer stable. To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling inheritFromWidgetOfExactType() in the widget's didChangeDependencies() method.
Run Code Online (Sandbox Code Playgroud)

buildSuggestions由于导航到,该方法的上下文在此期间变得陈旧ChooseOnMapPage

class _SuggestionList extends StatelessWidget {
  // ...
  void _handleOnChooseOnMapTap(BuildContext context) async {
    Location location = await Navigator.of(context).push(
      MaterialPageRoute<Location>(builder: (context) {
        return ChooseLocationPage();
      }),
    );
    onMapTapped(location);
  }
  // ...
}
Run Code Online (Sandbox Code Playgroud)

解决方法

当前的解决方法是显示结果,然后立即关闭搜索委托:

class LocationSearchDelegate extends SearchDelegate<Location> {
  // ...
  @override
  Widget buildSuggestions(BuildContext context) {
    return _SuggestionList(
      query: query,
      onSelected: (Location suggestion) {
        result = suggestion;
        close(context, result);
      },
      onMapTapped: (Location location) {
        result = location;
        showResults(context); // <- Throws NO exception
      },
    );
  }
  // ...
  @override
  Widget buildResults(BuildContext context) {
    Future.delayed(Duration.zero, () {
      close(context, result);
    });
    return Container();
  }
  // ...
}
Run Code Online (Sandbox Code Playgroud)

我不喜欢这种解决方法,所以有什么关于如何解决这个问题的建议吗?

Oma*_*att 0

错误的常见原因Looking up a deactivated widget's ancestor is unsafe.是应用程序正在尝试访问不可用的上下文。此问题的解决方法是使用Widget 上下文的GlobalKey 。