Flutter: get default context? or load assets without context?

你。 提交于 2021-02-09 07:31:38

问题


I'm trying to load a json file in a class extending SearchDelegate to search through its content.

I have a method to load this file:

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

Unfortunately this requires a Buildcontext (context) that seems only to be available in the SearchDelegate build methods (like buildActions, buildLeadings, etc), but no outside like for example in the constructor.

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

As the @override xy build methods in SearchDelegate are called with every change in the search field, I would load my file over and over again, which is of course not ideal. I want to load my file once at the beginning only.

Is there a way to get some sort of get default context that I could use for example in the constructor of SearchDelegate. Like in android (if I remmeber correctly)?

Or can I load an assets file without .of(context)?


回答1:


As DefaultAssetBundle is based on an InheritedWidget you will always need to pass a context.

of just looks up the widget tree based on a BuildContext until it finds a DefaultAssetBundle widget. This means that you cannot retrieve a DefaultAssetBundle object without a BuildContext.

You will need to pass a BuildContext to your method. I could imagine a situation like the following:

@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
  }
}

As you can see I passed the BuildContext from the build method. The FutureBuilder also allows to process the data in the build tree directly.




回答2:


Description of function

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

So you may simply use rootBundle instead of DefaultAssetBundle.of(context) for working with assets without context.




回答3:


There is an option to get builtin AssetBundle without specifying a reference to BuildContext. Here is an example of how it could be done:

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



回答4:


You can give the BuildContext as a parameter through to loadCountryData(BuildContext context).



来源:https://stackoverflow.com/questions/51109621/flutter-get-default-context-or-load-assets-without-context

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!