【问题标题】:How to access asset file in pure dart package?如何访问纯 dart 包中的资产文件?
【发布时间】:2021-08-23 06:05:30
【问题描述】:

原始问题

我编写了一个 dart 包,我的颤振应用程序正在使用它。 在 dart 包中,我想将一些静态数据存储在一个我想从 dart 包代码中读取的 json 文件中。

但是我找不到直接从 dart 包访问资产文件的方法。使用 File(path).readAsString() 仅适用于 dart 控制台应用程序,使用 rootBundle 仅适用于 Flutter 包/应用程序。

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

在颤振包中,我只需像这样通过 pubspec.yml 使文件可用

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

但我无法为纯 dart 包找到类似的解决方案。

感谢任何帮助。

回答

经过长时间的研究和社区的大力帮助,这个功能似乎根本不存在。

但是有一些解决方法:

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

通过rootBundle.loadString()从flutter项目中加载asset文件,并在flutterpubspec.yaml中指定asset文件,并将字符串数据传递给dart包。检查ch271828n's answer for details

让它成为一个颤振包

一个简单的解决方案是将纯 dart 包转换为颤振包。然后它就不再是纯飞镖了,但这并不总是有害的。尤其是在另一个 Flutter 项目/包中使用该包时。

将原始数据保存在变量中

除了提供资产文件并在运行时读取内容之外,您还可以直接将资产文件内容安全地保存到static const 变量中。但是,对于较大的资产,如果它从资产中索引数十万行,这可能会减慢您的 IDE。从分析器中排除这些文件可能会有所帮助: analysis_options.dart

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

阿斯彭包

您还可以查看aspen 包,该包可帮助解决之前的解决方案。您指定资产的路径,然后通过代码生成将这些文件的内容保存到可直接从代码中获得的变量中。

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

【问题讨论】:

    标签: json flutter file dart assets


    【解决方案1】:

    乍一看这是“不可能的”,因为 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 ...
    }
    

    在 Flutter 包中你要使用 pure-dart 包:

    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 将资产放入一个特殊的存档中,称为资产包,应用在运行时读取该存档。

    【讨论】:

    • 是的,IoC 是一种变通方法,但不是问题的真正解决方案。实际上,我不明白为什么它不起作用。独立于使用 dart 包的环境,如果资产文件位于 lib 文件夹中,如果您知道项目根目录的相对路径,则应该不难找到它们...
    • @tmaihoff 确实,不。 Flutter 的资产文件可能不存在于磁盘路径中的任何位置 - 例如可以压缩在 apk (android) 文件中。此外,您可能没有足够的权限执行此操作。
    • @tmaihoff 此外,“在构建过程中,Flutter 将资产放入一个特殊的归档文件中,称为资产包,应用程序在运行时从中读取。” (flutter.dev/docs/development/ui/…),所以它是在一个特殊的捆绑包中。
    • @tmaihoff 等一下——这个链接有用吗? ---> medium.com/@wangdazhitech/…
    • 不是真的,在链接中他们还使用了颤振导入import 'package:flutter/services.dart' show rootBundle;
    【解决方案2】:

    除了documentation,您应该使用 rootBundle 来加载您的 json:

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

    如果您在 Widget 中使用它,推荐给用户 DefaultAssetBundle.of(context)

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

    【讨论】:

    • 感谢您的回答,但这不是我想要的。您的解决方案仅适用于颤振包。我需要从纯 dart 包中访问资产文件。我更新了问题以使其更清楚
    • 可能是从内部定位包路径的问题。如果有帮助,请查看本教程:medium.com/@codetreeglobal/…
    • 是的,我知道这种方法。这仅适用于您可以访问计算机文件系统的控制台应用程序。当您尝试在 dart 包项目中找不到该文件时
    【解决方案3】:

    试试这个:

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

    【讨论】:

    • 这不适用于在颤振应用程序中使用的 dart 包。通过这种方式找不到文件。如果您有最小的工作示例,请分享它
    • 我在一个非颤振项目上使用了这个。在我提供这段代码之前,我通过创建一个 main.dart 和 demo.json 进行了测试,它通过运行 main 函数来工作。
    • 是的,在非颤振项目中这是有效的。但我需要一个在颤振包内的纯飞镖包中工作的解决方案
    猜你喜欢
    • 2021-01-02
    • 2022-07-02
    • 1970-01-01
    • 1970-01-01
    • 2019-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-14
    相关资源
    最近更新 更多