Flutter开发中自动生成资源文件类

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

像下面一样:

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();
  }
}
posted @ 2022-04-22 15:02  菠萝橙子丶  阅读(538)  评论(1编辑  收藏  举报