Flutter:获取默认上下文?或在没有上下文的情况下加载资产?

Chr*_*ris 3 flutter

我正在尝试在扩展 SearchDelegate 的类中加载一个 json 文件以搜索其内容。

我有一个方法来加载这个文件:

Future<void> loadCountryData() async {
    try {
      String data = await DefaultAssetBundle
          .of(context)
          .loadString("assets/data/countries.json");
      _countries = json.decode(data);
    } catch (e) {
      print(e);
    }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这需要一个 Buildcontext(上下文),它似乎只在 SearchDelegate 构建方法(如 buildActions、buildLeadings 等)中可用,但在构造函数中没有外部可用。

https://docs.flutter.io/flutter/material/SearchDelegate-class.html

由于 SearchDelegate 中的 @override xy 构建方法在搜索字段中的每次更改时都会被调用,因此我会一遍又一遍地加载我的文件,这当然不理想。我只想在开始时加载我的文件一次。

有没有办法获得某种我可以在 SearchDelegate 的构造函数中使用的默认上下文。就像在 android 中一样(如果我记得正确的话)?

或者我可以加载一个没有.of(context)?

Che*_*Max 8

有一个选项可以获取内置AssetBundle而不指定对 的引用BuildContext。以下是如何完成此操作的示例:

import 'package:flutter/services.dart'; // is required

Future<void> loadCountryData() async {
    try {
        // we can access builtin asset bundle with rootBundle
        final data = await rootBundle.loadString("assets/data/countries.json");
        _countries = json.decode(data);
    } catch (e) {
      print(e);
    }
}
Run Code Online (Sandbox Code Playgroud)


Vas*_*lov 6

功能说明

  /// The bundle from the closest instance of this class that encloses
  /// the given context.
  ///
  /// If there is no [DefaultAssetBundle] ancestor widget in the tree
  /// at the given context, then this will return the [rootBundle].
  ///
  /// Typical usage is as follows:
  ///
  /// ```dart
  /// AssetBundle bundle = DefaultAssetBundle.of(context);
  /// ```
  static AssetBundle of(BuildContext context) {
    final DefaultAssetBundle result = context.dependOnInheritedWidgetOfExactType<DefaultAssetBundle>();
    return result?.bundle ?? rootBundle;
  }
Run Code Online (Sandbox Code Playgroud)

因此,您可以简单地使用 rootBundle 而不是 DefaultAssetBundle.of(context) 来处理没有上下文的资产。


cre*_*not 1

由于DefaultAssetBundle基于 anInheritedWidget你总是需要传递一个 context

of只是根据 a 查找 widget 树,BuildContext直到找到一个DefaultAssetBundlewidget。这意味着您无法检索DefaultAssetBundle没有BuildContext.

需要将 a 传递BuildContext给您的方法。我可以想象这样的情况:

@override
Widget build(BuildContext context) {
  return FutureBuilder(
    future: loadCountryData(context: context),
    builder: (BuildContext context, AsyncSnapshot<JSON> jsonData) {
      if (!jsonData.hasData) {
        return Text('not loaded');
      }
      return Text('loaded'); // here you want to process your data
    },
  );
}

/// I am not sure what your decode returns, so I just called it JSON
/// I thought it would make more sense to return the JSON to use it in build
Future<JSON> loadCountryData({BuildContext context}) async {
  try {
    String data = await DefaultAssetBundle
      .of(context)
      .loadString("assets/data/countries.json");
    return json.decode(data);
  } catch(e) {
    print(e);
    return JSON.empty(); // imagine this exists
  }
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我通过了BuildContext方法build。还FutureBuilder允许直接处理构建树中的数据。