Flutter循环访问控制插件loop_visitor的使用
Flutter循环访问控制插件loop_visitor的使用
特性
- 允许处理数据而无需积累(例如处理目录中的文件或大型文本文件中的行)。
- 允许在调用者(循环)内部根据返回值(见VisitResult)对各种情况进行反应。
- 允许在异步循环中使用同步(阻塞)或异步(非阻塞)迭代处理器(在与文件系统相关的操作中非常有用,当同时需要同步和异步版本时)。
使用方法
该示例可以在example/loop_visitor_example.dart
中找到。
import 'dart:async';
import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:loop_visitor/loop_visitor.dart';
/// 应用特定的数据类
///
class DirEntryInfo {
/// 文件数量限制
///
static const int limit = 9;
/// 目录条目
///
FileSystemEntity? entity;
/// 条目的类型
///
/// 是的,`entity is File` 也可以工作,
/// 但目的是展示更复杂的东西
///
var type = FileSystemEntityType.notFound;
}
/// 过滤器(非阻塞)
///
Future<VisitResult> filterFiles(VisitParams<DirEntryInfo> params) async => filterFilesSync(params);
/// 过滤器(非阻塞)
///
VisitResult filterFilesSync(VisitParams<DirEntryInfo> params) {
final myEntity = params.current;
final entity = myEntity?.entity;
final type = myEntity?.type;
if ((entity == null) || (type != FileSystemEntityType.file)) {
return VisitResult.skip;
}
final takenNo = params.takenNo + 1;
print('$takenNo: ${entity.path}');
final pileup = params.pileup as List<String>?;
if (params.currentNo <= 1) {
pileup?.clear();
}
pileup?.add(entity.path);
return (takenNo >= DirEntryInfo.limit
? VisitResult.takeAndStop
: VisitResult.take);
}
/// 非阻塞方式遍历目录条目
///
Future<int> getTopFiles(FileSystem fs, String dirName, List<String> pileup,
VisitHandler<DirEntryInfo>? handler) async {
var myEntity = DirEntryInfo();
var result = VisitResult.take;
var params = VisitParams<DirEntryInfo>(
current: myEntity,
pileup: pileup,
isSyncCall: (handler is VisitHandlerSync));
var dirList = fs.directory(dirName).list();
await for (final entity in dirList) {
++params.currentNo;
myEntity.entity = entity;
myEntity.type =
(params.isSyncCall ? entity.statSync() : await entity.stat()).type;
if (handler != null) {
if (params.isSyncCall) {
result = handler(params) as VisitResult;
} else {
result = await handler(params);
}
}
if (result.isTake) {
++params.takenNo;
}
if (result.isStop) {
break;
}
}
return params.takenNo;
}
/// 阻塞方式遍历目录条目
///
int getTopFilesSync(FileSystem fs, String dirName, List<String> pileup,
VisitHandlerSync<DirEntryInfo>? handler) {
var myEntity = DirEntryInfo();
var result = VisitResult.take;
var params = VisitParams<DirEntryInfo>(
current: myEntity, pileup: pileup, isSyncCall: true);
var dirList = fs.directory(dirName).listSync();
for (final entity in dirList) {
++params.currentNo;
myEntity.entity = entity;
myEntity.type = entity.statSync().type;
if (handler != null) {
result = handler(params);
}
if (result.isTake) {
++params.takenNo;
}
if (result.isStop) {
break;
}
}
return params.takenNo;
}
/// 主入口点
///
Future<void> main(List<String> args) async {
final fs = LocalFileSystem();
final isSync = args.contains('-s');
final argsEx = [...args.where((x) => !x.startsWith('-'))];
if (argsEx.isEmpty) {
argsEx.add(fs.currentDirectory.path);
}
var count = 0;
var pileup = <String>[];
for (final arg in argsEx) {
print('''
--- 目录: "$arg"
''');
if (isSync) {
count = getTopFilesSync(fs, arg, pileup, filterFilesSync);
} else {
count = await getTopFiles(fs, arg, pileup, filterFiles);
}
print('''
总计: $count 文件,堆栈包含 ${pileup.length} 个路径:
$pileup
''');
}
}
示例代码
import 'dart:async';
import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:loop_visitor/loop_visitor.dart';
/// 应用特定的数据类
///
class DirEntryInfo {
/// 文件数量限制
///
static const int limit = 9;
/// 目录条目
///
FileSystemEntity? entity;
/// 条目的类型
///
/// 是的,`entity is File` 也可以工作,
/// 但目的是展示更复杂的东西
///
var type = FileSystemEntityType.notFound;
}
/// 过滤器(非阻塞)
///
Future<VisitResult> filterFiles(VisitParams<DirEntryInfo> params) async => filterFilesSync(params);
/// 过滤器(非阻塞)
///
VisitResult filterFilesSync(VisitParams<DirEntryInfo> params) {
final myEntity = params.current;
final entity = myEntity?.entity;
final type = myEntity?.type;
if ((entity == null) || (type != FileSystemEntityType.file)) {
return VisitResult.skip;
}
final takenNo = params.takenNo + 1;
print('$takenNo: ${entity.path}');
final pileup = params.pileup as List<String>?;
if (params.currentNo <= 1) {
pileup?.clear();
}
pileup?.add(entity.path);
return (takenNo >= DirEntryInfo.limit
? VisitResult.takeAndStop
: VisitResult.take);
}
/// 非阻塞方式遍历目录条目
///
Future<int> getTopFiles(FileSystem fs, String dirName, List<String> pileup,
VisitHandler<DirEntryInfo>? handler) async {
var myEntity = DirEntryInfo();
var result = VisitResult.take;
var params = VisitParams<DirEntryInfo>(
current: myEntity,
pileup: pileup,
isSyncCall: (handler is VisitHandlerSync));
var dirList = fs.directory(dirName).list();
await for (final entity in dirList) {
++params.currentNo;
myEntity.entity = entity;
myEntity.type =
(params.isSyncCall ? entity.statSync() : await entity.stat()).type;
if (handler != null) {
if (params.isSyncCall) {
result = handler(params) as VisitResult;
} else {
result = await handler(params);
}
}
if (result.isTake) {
++params.takenNo;
}
if (result.isStop) {
break;
}
}
return params.takenNo;
}
/// 阻塞方式遍历目录条目
///
int getTopFilesSync(FileSystem fs, String dirName, List<String> pileup,
VisitHandlerSync<DirEntryInfo>? handler) {
var myEntity = DirEntryInfo();
var result = VisitResult.take;
var params = VisitParams<DirEntryInfo>(
current: myEntity, pileup: pileup, isSyncCall: true);
var dirList = fs.directory(dirName).listSync();
for (final entity in dirList) {
++params.currentNo;
myEntity.entity = entity;
myEntity.type = entity.statSync().type;
if (handler != null) {
result = handler(params);
}
if (result.isTake) {
++params.takenNo;
}
if (result.isStop) {
break;
}
}
return params.takenNo;
}
/// 主入口点
///
Future<void> main(List<String> args) async {
final fs = LocalFileSystem();
final isSync = args.contains('-s');
final argsEx = [...args.where((x) => !x.startsWith('-'))];
if (argsEx.isEmpty) {
argsEx.add(fs.currentDirectory.path);
}
var count = 0;
var pileup = <String>[];
for (final arg in argsEx) {
print('''
--- 目录: "$arg"
''');
if (isSync) {
count = getTopFilesSync(fs, arg, pileup, filterFilesSync);
} else {
count = await getTopFiles(fs, arg, pileup, filterFiles);
}
print('''
总计: $count 文件,堆栈包含 ${pileup.length} 个路径:
$pileup
''');
}
}
更多关于Flutter循环访问控制插件loop_visitor的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter循环访问控制插件loop_visitor的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用loop_visitor
插件的一个示例。loop_visitor
插件通常用于在循环访问集合或列表时执行一些控制操作,比如中断循环、跳过某些元素等。不过,需要注意的是,loop_visitor
并不是Flutter官方或广泛认知的插件,这里我们假设它提供了一些类似功能的API。
由于loop_visitor
可能不是一个真实存在的Flutter插件(至少在我最后的知识更新时是这样),我将提供一个概念性的示例,展示如何在Flutter中手动实现类似的循环访问控制功能。
示例:手动实现循环访问控制
假设我们有一个列表,并希望在遍历这个列表时能够中断循环或跳过某些元素。我们可以使用Dart的迭代器和条件判断来实现这一点。
1. 创建一个Flutter项目
首先,确保你已经有一个Flutter项目。如果没有,可以使用以下命令创建一个新的Flutter项目:
flutter create loop_visitor_example
cd loop_visitor_example
2. 实现循环访问控制逻辑
在lib/main.dart
文件中,我们可以实现以下逻辑:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Loop Visitor Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final List<String> items = ['A', 'B', 'C', 'D', 'E'];
void visitItems(List<String> items) {
for (int i = 0; i < items.length; i++) {
String item = items[i];
// 假设我们有一个条件来中断循环
if (item == 'C') {
print('Breaking loop at item: $item');
break;
}
// 假设我们有一个条件来跳过当前元素
if (item == 'B') {
print('Skipping item: $item');
continue;
}
print('Visited item: $item');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Loop Visitor Example'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
visitItems(items);
},
child: Text('Visit Items'),
),
),
);
}
}
3. 运行应用
现在,你可以运行这个Flutter应用,点击按钮后,你会在控制台看到如下输出:
Visited item: A
Skipping item: B
Visited item: D
Breaking loop at item: C
解释
visitItems
方法遍历items
列表。- 如果当前元素是
'C'
,则中断循环。 - 如果当前元素是
'B'
,则跳过当前元素,继续下一个迭代。 - 其他情况下,打印当前元素。
通过这种方式,你可以在Flutter中实现类似于循环访问控制的功能,而无需依赖一个不存在的loop_visitor
插件。如果你确实找到了一个名为loop_visitor
的插件,并且它提供了类似的功能,那么你可以参考它的文档来集成和使用它。不过,基于现有的Dart和Flutter功能,上述示例已经展示了如何在循环中控制访问。