添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

在开发程序时,我们少不了会使用到很多资源文件,一般我为了方便,会把这些资源文件都放在一个类里面,容易管理。

像下面一样:

const String iconPath = 'assets/icons';
class AppIcons {
  static String menu = '$iconPath/menu.jpg';

但是,如果我们在项目中用到10个或以上的资源文件的时候,一个一个定义就很麻烦,一不小心还会看走眼出错。所以,我打算自己定义一个方法,来自动生成这些文件。

我们需要知道文件夹所在位置,所以需要用到path这个包

import 'package:path/path.dart' as path;

我们需要获取要访问的资源文件路径

void generateAssets(String dir) {
  String assetsPath = path.join(path.current, dir);

dir是我们要访问的文件夹名称,assetsPath就是我们存储的文件夹路径。

这里之所以使用一个参数来使用,是为了方便递归资源文件夹下面的文件夹。我们现在得到的还不是一个文件夹对象,它只是String类型的路径,所以我们需要将它转成一个文件夹对象

Directory directory = Directory(assetsPaht);

在正式访问该文件夹前,我们还需要让程序知道这个文件夹是否存在,如果不存在就让它自动创建,并递归一下该方法(当然,一般我们开发时该文件夹已存在,并已经放置好了所有需要用到的资源)

if (directory.existsSync()) {
  // 文件夹存在进行的操作
} else {
  directory.createSync();
  generateAssets(dir);

如果存在,我们继续下一步操作。我们需要获取该文件夹下面的所有子文件或文件夹

List<FileSystemEntity> files = directory.listSync();

如果该文件夹下的子文件或文件夹为空,我们就不进行任何操作。如果存在文件或文件夹就继续操作

if (files.isNotEmpty) {
  // 文件夹不为空进行的操作
} else {
  print('该文件夹为空');

当然,文件夹下的内容可能不止一个,所以我们需要遍历一遍。还要判断是文件夹还是文件,来进行不同的操作

for(var file in files) {
  if (file.statSync().type == FileSystemEntityType.file) {
    // 是文件的操作
  } else {
    // 是文件夹就继续遍历
    generateAssets(file.path);

如果是文件,我们需要存储文件名和文件夹名用来生成使用

List<String> allFile = [];
String dirName = '';
if (file.statSync().type == FileSystemEntityType.file) {
  dirName = path.basename(file.parent.path);
  String fileName = path.basename(file.path);
  allFile.add(fileName);

获取了所有文件名,接下来就是最主要的,用方法来生成类。

在这个方法中,我设置了3个需要传入的参数,分别是:

  • List allFile:获取到的所有文件名称
  • String dirname:文件所在文件夹的名称,用来生成类文件名用
  • String generateDir:生成的类文件所在的文件夹
  • void autoGenerate(List<String> allFile, String dirName, String generateDir) {
    

    先来设置生成的文件的路径

    String utilsPath = path.join(path.current, 'lib', generateDir, '$dirName.dart');
    File file = File(utilsPath);
    

    如果路径文件不存在,我们就要生成。

    if (file.existsSync()) {
    } else {
      file.createSync();
      autoGenerate(allFile, dirName, generateDir);
    

    文件存在我们就写入内容

    if (file.existsSync()) {
      String contents = '''
    const String ${dirName}Path = 'assets/$dirName';
    class App${dirName.capitalize()} {''';
      for (var file in allFile) {
        String fileName = file.contains('-')
            ? file.hump('-').split('.').first
            : file.split('.').first;
        contents += "static String $fileName = '\$${dirName}Path/$file';";
      contents += '}';
      file.writeAsStringSync(contents);
    

    这里为了方便,扩展了两个String类型的方法

    extension StringExtension on String {
      // 首字母大写
      String capitalize() {
        return "${this[0].toUpperCase()}${substring(1)}";
    	// 驼峰式命名
      String hump(String interval) {
        List<String> allChar = split(interval);
        for (var i = 1; i < allChar.length; i++) {
          allChar[i] = allChar[i].capitalize();
        return allChar.join();
    

    还要更改一下generateAssets传入的参数,并在这个方法中调用autoGenerate

    void generateAssets(String dir, String generateDir) {
        if (files.isNotEmpty) {
          autoGenerate(allFile, dirName, generateDir);
    

    所有的方法都写好了,现在只有调用就行。

    /// [dir]资源所在文件夹
    /// [generateDir]传入生成的类所在文件夹
    void generateAssets(String dir, String generateDir) {
      List<String> allFile = [];
      String dirName = '';
      String assetsPaht = path.join(path.current, dir);
      Directory directory = Directory(assetsPaht);
      if (directory.existsSync()) {
        List<FileSystemEntity> files = directory.listSync();
        if (files.isNotEmpty) {
          for (var file in files) {
            if (file.statSync().type == FileSystemEntityType.file) {
              dirName = path.basename(file.parent.path);
              String fileName = path.basename(file.path);
              allFile.add(fileName);
            } else {
              generateAssets(file.path, generateDir);
          autoGenerate(allFile, dirName, generateDir);
        } else {
          print('该文件夹为空');
      } else {
        directory.createSync();
        generateAssets(dir, generateDir);
    void autoGenerate(List<String> allFile, String dirName, String generateDir) {
      if (allFile.isNotEmpty) {
        String utilsPath =
            path.join(path.current, 'lib', generateDir, '$dirName.dart');
        File file = File(utilsPath);
        if (file.existsSync()) {
          String contents = '''
    const String ${dirName}Path = 'assets/$dirName';
    class App${dirName.capitalize()} {''';
          for (var file in allFile) {
            String fileName = file.contains('-')
                ? file.hump('-').split('.').first
                : file.split('.').first;
            contents += "static String $fileName = '\$${dirName}Path/$file';";
          contents += '}';
          file.writeAsStringSync(contents);
        } else {
          file.createSync();
          autoGenerate(allFile, dirName, generateDir);
    extension StringExtension on String {
      String capitalize() {
        return "${this[0].toUpperCase()}${substring(1)}";
      String hump(String interval) {
        List<String> allChar = split(interval);
        for (var i = 1; i < allChar.length; i++) {
          allChar[i] = allChar[i].capitalize();
        return allChar.join();