flutter 如何访问纯dart包中的资产文件?

xmq68pz9  于 2023-01-31  发布在  Flutter
关注(0)|答案(5)|浏览(200)

我写了一个dart包,它被我的flutter应用程序使用。在dart包里面,我想把一些静态数据存储在一个json文件中,我想从dart包代码中读取这些数据。
但是我找不到直接从dart包访问asset文件的方法,使用File(path).readAsString()只能用于dart控制台应用程序,使用rootBundle只能用于flutter包/应用程序。

    • 我的问题是:如何直接从纯dart包访问存储在dart包资产中的此文件?**

在flutter包中,我会简单地通过pubspec.yml提供该文件,如下所示

flutter:
   assets:
      - lib/assets/b737.json

但是对于纯dart包,我找不到类似的解决方案。

sxissh06

sxissh061#

乍一看是"不可能"的,因为Dart软件包可以在任何地方使用--例如在非Flutter环境中使用。然后就真的没有办法找到它。
但是,有一个解决方法:inverse of control。示例代码:

// pure dart package

abstract class AbstractAssetFileFetcherService {
  String getAssetFileContent(String assetName);
}

AbstractAssetFileFetcherService? service;

void myFunctionThatUsesAssetFile() {
  var myFirstFileContent = service.getAssetFileContent('my-first-file-name.png');
  var mySecondFileContent = service.getAssetFileContent('my-second-file-name.json');
  // ... use the file content happily ...
}

在您想要使用纯 dart 包的Flutter包中:

void main() {
  service = AssetFileFetcherService(); // or use other IoC methods such as the `GetIt` Dart package
  myFunctionThatUsesAssetFile();
}

class AssetFileFetcherService extends AbstractAssetFileFetcherService {
  String getAssetFileContent(String assetName) {
    return rootBundle.loadString(assetName); // just use any normal method. you are in Flutter environment here.
  }
}
    • 编辑**

Flutter的资产文件可能不存在于磁盘路径的任何地方-例如,它可以压缩在apk(android)文件中。此外,您可能没有足够的权限来执行此操作。
https://flutter.dev/docs/development/ui/assets-and-images#asset-bundling
在构建过程中,Flutter将资产放入一个称为资产包的特殊归档中,应用程序在运行时从该归档中读取。

9rygscc1

9rygscc12#

对于documentation,您应该使用rootBundle来加载json:

String   jsonString =  await rootBundle.loadString('assets/b737.json');

如果您在小部件内部使用它,建议用户DefaultAssetBundle.of(context)使用

String jsonString = await DefaultAssetBundle
      .of(context)
      .loadString("assets/b737.json");
8zzbczxx

8zzbczxx3#

试试这个:

final stringData = await File('data.json').readAsString();
final data = json.decode(stringData);
yrdbyhpb

yrdbyhpb4#

作为aspen包的意外替代,我编写了一个resource_importer包,它也使用代码生成将数据存储为文本(如果我当时知道aspen,我可能就不会编写它了。
用法有点不同;通过pubspec.yaml指定资产。例如:

resource_importer:
  resources:
    myImage: 'assets/image.png'
    myLicense:
      path: 'LICENSE'
      type: String
ergxz8rk

ergxz8rk5#

溶液总结

经过长时间的研究和社区的帮助,这个功能似乎根本不存在。
但也有变通办法:

从Flutter项目加载并将读取字符串传递到dart包

通过rootBundle.loadString()从flutter项目加载资产文件,在flutter pubspec.yaml中指定资产文件,并将字符串数据传递给dart包。

让它成为一个Flutter包

一个简单的解决方案是将纯dart包转换为flutter包,这样它就不再是纯dart了,但这并不总是有害的,特别是当这个包被用于另一个flutter项目/包时。

将原始数据保存在变量中

您也可以直接将资源文件内容安全地保存到一个静态常量变量中,而不是提供资源文件并在运行时阅读内容。但是,对于较大的资源,如果IDE从资源中索引成百上千行,这可能会降低IDE的速度。从分析器中排除这些文件可能会有所帮助:分析_选项.dart

analyzer:
  exclude:
    - '**/assets/data/**'

白杨包

你也可以 checkout 白杨软件包来帮助你解决之前的问题,你可以指定资源的路径,然后通过代码生成将这些文件的内容保存到变量中,这些变量可以直接从代码中获得。

part 'assets.g.dart';

// @Asset is an annotation from package:aspen that marks the asset to be packed.
@Asset('asset:my_package/web/my-asset.txt')
// We create a const (it must be const!) value that holds the generated asset content.
const myTextAsset = TextAsset(text: _myTextAsset$content);

相关问题