颤振:获取默认上下文? 还是加载没有上下文的资产?



我正在尝试在扩展 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);
}
}

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

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

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

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

或者我可以在没有.of(context)的情况下加载资产文件吗?

函数描述

/// 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;
}

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

有一个选项可以在不指定对BuildContext的引用的情况下获取内置AssetBundle。下面是如何完成的示例:

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);
}
}

由于DefaultAssetBundle是基于InheritedWidget因此您始终需要传递上下文

of只是根据BuildContext查找小部件树,直到找到DefaultAssetBundle小部件。这意味着如果没有BuildContext,则无法检索DefaultAssetBundle对象。

您需要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
}
}

如您所见,我通过了build方法的BuildContext。该FutureBuilder还允许直接处理构建树中的数据。

您可以将BuildContext作为参数提供给loadCountryData(BuildContext context)

最新更新