quicklibs 1.1.9

  • Readme
  • Changelog
  • Installing
  • 81

开始使用 #

当前最新版本为: 1.1.9

在 "pubspec.yaml" 文件中加入

dependencies:
  quicklibs: ^1.1.9

github

https://github.com/CimZzz/quicklibs

Usage #

  • 迭代器: 用提供闭包来实现循环每一步控制逻辑

  • Time: 提供一系列关于时间的操作,如时间格式化,字符串转时间等方法

  • 转换方法: 提供一系列关于转换具体类型的操作

  • Scope: 提供在限定的作用域内,有状态无状态消息之间的交互。

迭代器 #

闭包命名

typedef EachBeginCallback<T> = T Function();
typedef EachCallback<T> = Function(T elem);
typedef EachJudgeCallback<T> = bool Function(T obj);
typedef EachChangeCallback<T> = T Function(T obj);
typedef EachOverCallback = dynamic Function(dynamic obj);
typedef EachOverAsCallback<T> = T Function(dynamic obj);
  • EachBeginCallback
  • EachCallback
  • EachJudgeCallback
  • EachChangeCallback
  • EachOverCallback 处理循环结果闭包回调,一般在循环执行完成后调用
  • EachOverAsCallback

以 for 循环为例(仅仅为参考样例)

for(var i = 0 ; i < 10 ; i ++) {
	
};

将回调带入后

for(EachBeginCallback; EachJudgeCallback; EachChangeCallback) {
    final result = EachCallback;
    if(result != null)
    	return EachOverCallback(result);
}

迭代构造器 EachBuilder<T>

提供一系列构造迭代器的方法

EachBuilder begin(EachBeginCallback<T> beginCallback); //构建一次循环回调闭包

EachBuilder change(EachChangeCallback<T> changeCallback); //构建末尾循环体回调闭包

EachBuilder judge(EachJudgeCallback<T> judgeCallback); //构建判断循环终止回调闭包

EachBuilder call(EachCallback<T> callback); //构建循环体回调闭包

EachBuilder configAll({
    EachBeginCallback<T> beginCallback,
    EachChangeCallback<T> changeCallback,
    EachJudgeCallback<T> judgeCallback,
    EachCallback<T> callback
}); // 一次性配置全部回调(空闭包会被忽略)

void loopOnly(); // 只执行循环不考虑结果

EachResult loop(); // 执行循环返回结果 EachResult

E loopForResult<E>(); // 执行循环直接获取最终结果

List<E> loopForList<E>(); // 执行循环直接获取最终指定类型列表

loopOnly 例子如下:

loop1() {
	final builder = EachBuilder<int>();
	builder.begin(() => 0);
	builder.judge((position) => position < 5)
		.change((position) => position + 1)
		.call((position) => print(position))
		.loopOnly();
}

执行结果为:

0
1
2
3
4

如果循环需要返回值,可以通过 loop 函数来获取循环结果, 至于返回值,可以通过 EachCallback

  1. 返回类型为 EachResult 类型,强制中断循环返回 EachResult
  2. 返回类型为 非EachResult 类型,将值存入临时的 List 中(不保证下标位置关系), 在循环结束后返回一个包装 List 对象的 EachResult 对象

loop 例子如下:

loop2() {
	final list = EachBuilder<int>()
			.begin(() => 0)
			.judge((position) => position < 5)
			.change((position) => position + 1)
			.call((position) => position)
			.loop()
			.end();
	
	print(list);
}

执行结果为:

[0, 1, 2, 3, 4]

或者使用 loopForResult 来实现同样的功能

loop3() {
	final list = EachBuilder<int>()
		.begin(() => 0)
		.judge((position) => position < 5)
		.change((position) => position + 1)
		.call((position) => position)
		.loopForResult();
	
	print(list);
}

同样,loopForList 也能实现同样功能,并且会返回一个明确类型的列表而不是 dynamic 类型的列表

loop12() {
	final list = EachBuilder<int>()
		.begin(() => 0)
		.judge((position) => position < 5)
		.change((position) => position + 1)
		.call((position) => position)
		.loopForList<int>();
	
	print(list);
}

迭代结果 EachResult #

如果使用迭代构造器的 loop 方法,则会在执行结束后返回 EachResult 作为循环结果

我们可以操作这个 EachResult 对象来处理返回结果

提供一些处理迭代结果的方法:

EachResult then(EachOverCallback overCallback); // 追加处理结果回调

T as<T>(EachOverAsCallback<T> overCallback); // 执行一次处理结果回调后返回有具体类型的结果

dynamic end(); // 返回结果

注意: 当 EachResult 返回结果后,无法通过任何方式追加处理结果回调

下面这个例子,通过循环产生一个整数数组,然后通过结果处理返回数组之和:

loop4() {
	final value = EachBuilder<int>()
		.begin(() => 0)
		.judge((position) => position < 5)
		.change((position) => position + 1)
		.call((position) => position)
		.loop() // 返回 EachResult
		.then((list) {
			var sum = 0;
			list.forEach((num) {
				sum += num;
			});
			return sum;
		})
		.end();
	print(value);
}

执行结果如下:

10

这个处理结果是单链表结构,意味着可以链接多个处理回调。当收到返回结果为 EachResult 类型时,则不在执行下去忽略其余处理回调,如:

loop5() {
	final value = EachBuilder<int>()
		.begin(() => 0)
		.judge((position) => position < 5)
		.change((position) => position + 1)
		.call((position) => position)
		.loop() // 返回 EachResult
		.then((list) {
		var sum = 0;
		list.forEach((num) {
			sum += num;
		});
		return sum;
		})
		.then((sum){
			return sum * 10;
		})
		.then((sum) {
			return sum + 50;
		})
		.then((sum){
			return EachResult(sum - 1);
		})
		.then((sum) {
			return sum * 10000;
		})
		.end();
	print(value);
}

执行结果为:

149

如果可以明确最后一个处理回调,建议使用 as 方法

需要注意的是此方法不能返回 EachResult 类型对象

loop6() {
	final value = EachBuilder<int>()
		.begin(() => 0)
		.judge((position) => position < 5)
		.change((position) => position + 1)
		.call((position) => position)
		.loop() // 返回 EachResult
		.then((list) {
            var sum = 0;
            list.forEach((num) {
                sum += num;
            });
            return sum;
        })
        .then((sum){
            return sum * 10;
        })
        .then((sum) {
            return sum + 50;
        })
        .as((sum){
            return sum - 1;
        });
	print("value type: ${value.runtimeType}, value: $value");
}

执行结果为:

value type: int, value: 149

简化整数迭代器 #

常规循环通过构造器方式直接创建太过繁琐复杂,因为我们并不需要那么强的兼容性, 我们这里封装了一种常用的整数迭代器,具体还是使用迭代构造器来实现的,绝大部分迭代逻辑无需自己实现


/// 快捷生成整数循环迭代器的方法,返回最终结果
/// 通过 [intEachBuilder] 生成整数循环构造器,通过返回的 EachBuilder<int> 获得返回值
dynamic intEach({
		int start = 0,
		int end = 0,
		int total = 0,
		EachCallback<int> callback,
		EachChangeCallback<int> changeCallback
	});

/// 快捷生成整数循环迭代器的方法,返回最终 List 结果
/// 通过 [intEachBuilder] 生成整数循环构造器,通过返回的 EachBuilder<int> 获得返回 List 值
List<E> intEachList<E>({
	int start = 0,
	int end = 0,
	int total = 0,
	EachCallback<int> callback,
	EachChangeCallback<int> changeCallback
	});

/// 快捷生成整数循环迭代器的方法,返回 EachBuilder<int>
EachBuilder<int> intEachBuilder({
		int start = 0,
		int end = 0,
		int total = 0,
		EachCallback<int> callback,
		EachChangeCallback<int> changeCallback
	});
  • EachCallback 循环回调
  • start 起始下标(可选)
  • end 终止下标(可选)
  • total 表示循环总数(可选)
  • EachChangeCallback 循环执行末尾回调,用于提供自增/自减方法变化下标

以下实例均以 "intEach" 方法为例

举个例子,一个最简单的循环

loop7() {
	var i = 0;
	intEach(
		callback: (position) {
		//do something
		i += position;
	}, total: 100);
	
	print(i);
}

上述程序结果为 4950,等同于 ∑99。

同样也可以写作

loop8() {
	var i = 0;
	intEach(
		callback: (position) {
		//do something
		i += position;
	}, start: 0, end: 100);
	
	print(i);
}

结果同样为 4950

上述两个例子展示了执行整数迭代循环的两种方式,下面总结一下全部的方式

  1. 提供 total 参数与 start 参数,表示从 start 对应的下标开始,循环 total 次
  2. 提供 start 参数与 end 参数,表示从 start 对应下标开始,到 end 下标终止(遵循 "左闭右开" 原则)
changeCallback #

整数迭代器会跟传递的参数自动识别迭代的方向(正/负),提供默认的 自增/自减 闭包。

当然,如果普通的自增自减无法满足需求(比如以指数增长),可以通过 changeCallback 来决定增长趋势

loop9() {
	intEach(
		callback: (position) {
		//do something
		print("curPosition: $position");
	}, total: 100, changeCallback: (position) => position == 0 ? 1 : position * 3);
}

上述程序执行结果如下:

curPosition: 0
curPosition: 1
curPosition: 3
curPosition: 9
curPosition: 27
curPosition: 81

注意: changeCallback 增长方向要与实际方向一致,否则循环不会执行

简化列表迭代器 #

有些时候原生的 list-for-each 方式并不能满足我们的需求, 我们提供了简化的列表迭代器

/// 快捷生成列表循环迭代器的方法,返回最终结果
/// 通过 [listEachBuilder] 生成整数循环构造器,通过返回的 EachBuilder<int> 获得返回值
dynamic listEach<T>(List<T> list,{
	EachCallback<T> callback
});

/// 快捷生成列表循环迭代器的方法,返回 EachBuilder<int>
EachBuilder<int> listEachBuilder<T>(List<T> list,{
	EachCallback<T> callback
});

下面演示一个简单的列表遍历

loop13() {
	listEach([1, 2, 3, 4, 5],
	callback: (item) {
		print(item);
	});
}

执行结果如下:

1
2
3
4
5

我们可以利用 EachBuilder 的特性,来完成列表一些特殊操作,如下

loop14() {
	var list = ["1", "2", "3", "4", "5"];
	var newList = listEachBuilder(
		list,
		callback: (item) {
			return int.parse(item);
		}
	).loopForList<int>();
	
	print("list type: ${list.runtimeType}, $list");
	print("newList type: ${newList.runtimeType}, $newList");
}

执行结果如下:

list type: List<String>, [1, 2, 3, 4, 5]
newList type: List<int>, [1, 2, 3, 4, 5]

注意: 前提是在 callback 回调中返回对应的类型,否则会自动筛选列表,将满足指定类型的元素重新组成一个新的列表

中断循环 #

对于大部分闭包循环来说,中断循环始终是一个烦人的问题。不过通过这个迭代器,只要在迭代回调中返回由 EachResult 包装的值, 可以很轻易的实现中断闭包循环,而这个值还会当做迭代的最终结果返回

注意: 如果返回值不使用 EachResult 包装,则会记录到一个内部的临时列表中,在循环正常结束后将会返回该列表。如果没有返回值则 不会触发任何逻辑

如下方一个整数迭代器:


loop10() {
	var i = 0;
	var j = 
	intEach(
		callback: (position) {
		if(position > 50)
			return EachResult(i);
		i += position;
	}, total: 100);
	
	print("i: $i, j: $j");
}

执行结果为:

i: 1275, j: 1275

快速通过迭代生成列表 #

在每次迭代返回一个整数值,当循环结束后可以获得由返回值组成的一个列表

如下方一个整数迭代器:

loop11() {
	var list = 
	intEach(
		callback: (position) {
		return position * 10;
	}, total: 10);
	
	print(list);
}

执行结果为:

[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]

Time #

提供了一系列关于操作时间的方法,通过 Time 类来访问其中方法

闭包命名

typedef TimeFormatCallback = void Function(DateTime, int, StringBuffer);
typedef TimeParseCallback = void Function(_TimeParseBuilder, String);
typedef TimeFormatter = String Function(DateTime);
typedef TimeParser = int Function(String);

缺省的时间占位符

  • y: 表示年份
  • M: 表示月份
  • d: 表示天
  • H: 表示小时(全时制)
  • m: 表示分钟
  • s: 表示秒

时间格式化 #

将 DateTime 按照指定格式转化成字符串

static String format(
     DateTime dateTime,
     String formatStr,
     {List<TimePlaceholder> otherPlaceholder}
)
  • dateTime DateTime 实例
  • formatStr 格式化字符串,如 "yyyy-MM-dd HH:mm:ss"
  • otherPlaceholder 其他自定义时间占位符(可选)

示例如下

void example1() {
	print(Time.format(DateTime.now(), "yyyy-MM-dd HH:mm:ss"));
}

执行结果:

2019-06-04 14:56:14

时间格式化方法对象 #

将格式化方法包装成闭包对象返回,每次调用只需传递 DateTime 作为参数即可

将格式化中一些对象进行复用,优化了执行效率

static TimeFormatter generateFormatMethod(
    String formatStr,
    {List<TimePlaceholder> otherPlaceholder}
)
  • formatStr 格式化字符串,如 "yyyy-MM-dd HH:mm:ss"
  • otherPlaceholder 其他自定义时间占位符(可选)

返回 TimeFormatter 类型的闭包对象

示例如下

void example2() {
	final method = Time.generateFormatMethod("yyyy-MM-dd HH:mm:ss");
	print(method(DateTime.now()));
}

执行结果:

2019-06-04 14:56:14

时间解析方法 #

将字符串按照指定格式转化为 时间戳(注意不是 DateTime 实例)

注意: 如果源字符串中包含非占位符,用 "*" 来代替

static int parse(
    String sourceStr, 
    String formatStr, 
    {
    	List<TimePlaceholder> otherPlaceholder, 
    	bool isSafe = false, 
    	Duration timeZoneOffset
    }
)
  • sourceStr 源字符串,如 "2019-06-04 15:05:25"
  • formatStr 格式化字符串,如 "yyyy*MM*dd*HH*mm*ss"
  • otherPlaceholder 其他自定义时间占位符(可选)
  • isSafe 如果为 true,解析发生异常时返回 null,否则会抛出异常(可选)
  • timeZoneOffset 时区偏移量,默认为本地时区(可选)

示例如下:

void example3() {
	print(Time.parse("2019-06-04 15:05:25", "yyyy*MM*dd*HH*mm*ss"));
}

执行结果:

1559631925000 // 本人在东八区,北京时间

时间解析方法对象 #

将解析方法包装成闭包对象返回,每次调用只需传递源字符串作为参数即可

将解析化中一些对象进行复用,优化了执行效率

static TimeParser generateParseMethod(
    String formatStr, 
    {
    	List<TimePlaceholder> otherPlaceholder, 
    	bool isSafe = false, 
    	Duration timeZoneOffset
    }
)
  • formatStr 格式化字符串,如 "yyyy*MM*dd*HH*mm*ss"
  • otherPlaceholder 其他自定义时间占位符(可选)
  • isSafe 如果为 true,解析发生异常时返回 null,否则会抛出异常(可选)
  • timeZoneOffset 时区偏移量,默认为本地时区(可选)

返回 TimeParser 类型的闭包对象

示例如下:

void example4() {
	final method = Time.generateParseMethod("yyyy*MM*dd*HH*mm*ss");
	print(method("2019-06-04 15:05:25"));
}

执行结果:

1559631925000

测量执行时间 #

在开发测试中,会需要测量某段代码具体的执行时间,来选择最优的算法

提供了一个用来满足这个需求的方法

static Duration measure(void run())
  • run 表示执行方法函数闭包

示例如下:

void example5() {
	final duration = Time.measure(() {
		print("hello world");
	});
	
	print(duration);
}

执行结果:

hello world
0:00:00.000369

利用这个方法,我们可以来比较一下时间解析方法的效率

void example6() {
	final loopCount = 10000;
	
	final duration1 = Time.measure(() {
	intEach(
		callback: (position) {
			DateTime.parse("2019-06-04 15:05:25");
		}, total: loopCount);
	});
	
	final duration2 = Time.measure(() {
	intEach(
		callback: (position) {
			Time.parse("2019-06-04 15:05:25", "yyyy*MM*dd*HH*mm*ss");
		}, total: loopCount);
	});
	
	
	final duration3 = Time.measure(() {
		final method = Time.generateParseMethod("yyyy*MM*dd*HH*mm*ss");
	intEach(
		callback: (position) {
			method("2019-06-04 15:05:25");
		}, total: loopCount);
	});
	
	
	print("dart 原生Api解析 $loopCount 次耗时: $duration1");
	print("Time 直接解析 $loopCount 次耗时: $duration2");
	print("Time 生成解析方法解析 $loopCount 次耗时: $duration3");
}

执行结果:

dart 原生Api解析 10000 次耗时: 0:00:00.233731
Time 直接解析 10000 次耗时: 0:00:00.089006
Time 生成解析方法解析 10000 次耗时: 0:00:00.012564

从结果可见,生成解析方法比原生方法大约快 20 倍左右

转换方法 #

转化动态对象为指定类型列表 #

/// 如果 needPicker 为 false 时,只有 obj 是 List<T> 类型才会返回具体值,否则一律返回 null
/// 如果 needPicker 为 true 时,分多种情况拾取指定类型的对象
/// 1. obj 是 Iterable 的子类,遍历迭代器,将所有指定类型的对象放入新的列表中,返回新的列表
/// 2. obj 是指定类型对象,则将对象包装到一个新的列表中,返回新的列表
List<T> convertTypeList<T>(dynamic obj, {bool needPicker = false});

示例如下:

void convert1() {
	final list = [1, "2", 5];
	print(convertTypeList<String>(list, needPicker: false));
}

void convert2() {
	final list = [1, "2", 5];
	print(convertTypeList<String>(list, needPicker: true));
}

执行结果为:

null
[2]

转换对象为指定类型 #

/// 转换对象为指定类型
/// 如果对象为 null 或者对象类型不匹配则返回 null
T castTo<T>(dynamic obj)

实例如下:

/// 转换对象
void convert3() {
	dynamic number = 123;
	print(castTo<String>(number));
	print(castTo<int>(number));
}

执行结果为:

null
123

Scope #

抽象了一个拥有状态的作用域:

  1. Activated (启用状态)
  2. Deactivated (禁用状态)
  3. Destroy (销毁状态)

闭包命名

typedef ScopeMessageCallback = Future Function(dynamic obj);
typedef ScopeActiveDelayMessageCallback = void Function(Map<dynamic, dynamic>);
typedef ScopeBroadcastReceiver = Function(dynamic obj);
typedef ScopeProxyAsyncRunnable<T> = Future<T> Function();
typedef ScopeProxySyncRunnable<T> = Future<T> Function();

主要使用用例 #

img

可使用接口描述 #

/// 激活指定 Scope
static activate(Scope scope);
/// 关闭指定 Scope
static deactivate(Scope scope);
/// 销毁指定 Scope
static destroy(Scope scope);
/// 将指定 Scope 作为自己子 Scope
T fork<T extends Scope>(T scope);
/// 将调用的 Scope 与上级 Scope 断开
void dropSelf();
/// 将调用的 Scope 与全部子 Scope 断开
void dropChildren();
/// 注册消息接收器
/// 默认在关闭状态也可以接收
void registerMessageCallback(dynamic key, ScopeMessageCallback callback);
/// 注册消息接收器
/// 可以指定在何种状态下可以接收
void registerStatusMessageCallback(dynamic key, ScopeStatus allowRunStatus, ScopeMessageCallback callback);
/// 注销消息接收器
void unregisterMessageCallback(dynamic key);
/// 向下分发一次性消息,在消息第一次被接收后停止分发
/// 该方法可以返回处理后的结果
Future dispatchOneTimeMessage(dynamic key, dynamic data, {bool allowTraceBack = false, bool onlyTrackBack = false}) async;
/// 向下分发消息,会触发相同 key 值下全部的接收器
Future dispatchMessage(dynamic key, dynamic data) async;
/// 向上分发消息
/// 由该 Scope 向父级 Scope 传递消息
Future dispatchParentMessage(dynamic key, dynamic data, { int traceCount = 1}) async;
/// 分发同代消息
/// 对自己及同父 Scope 下的表兄弟分发消息
Future dispatchCousinMessage(dynamic key, dynamic data) async
/// 分发一次性同代消息
/// 当找到可以处理对应消息的消息回调时,将会中断遍历立即返回执行结果(Future)
Future dispatchCousinOneTimeMessage(dynamic key, dynamic data) async
/// 向指定 id 的子 Scope 分发消息
/// 如果直接子 Scope 不存在指定 id,可以设置 `onlyAllowDirectChildren = false`
/// 进行深度遍历.
Future dispatchSpecifiedMessage(dynamic id, dynamic key, dynamic data, { bool onlyAllowDirectChildren = true } ) async
/// 注册活动延迟消息回调
/// 只可注册一次
void registerActiveDelayCallback(ScopeActiveDelayMessageCallback callback);
/// 发送活动延迟消息
void postActiveDelayMessage(dynamic key, dynamic data);
/// 重置活动延迟消息相关资源
void resetActiveDelay();
/// 发送广播给对应 key 下注册的全部广播接收器
static void broadcast(dynamic key, dynamic data) async;
/// 注册广播接收器
void registerBroadcast(dynamic key, ScopeBroadcastReceiver receiver);
/// 注销广播接收器
/// 如果指定广播接收器的话,则只注销指定的广播接收器,否则会将指定 key 值下全部的广播接收器全部注销
void unregisterBroadcast(dynamic key, {ScopeBroadcastReceiver receiver});
/// 代理执行 Future
/// 当 Scope 状态为销毁状态时不会指定并返回 null
Future<T> proxyAsync<T>(ScopeProxyAsyncRunnable<T> runnable) async;
/// 代理同步执行回调
/// 当 Scope 状态为销毁状态时返回 null
T proxySync<T>(ScopeProxySyncRunnable<T> runnable);
/// 设置存储数据
/// 可以设置 `syncParent = true`,同时会将数据同步到父 Scope 中;若想同步全部父 Scope,
/// 设置 `untilNotExistParent = true` 会一直向上同步,直到到达顶级 Scope.
T setStoredData<T>(dynamic key, T data, { bool syncParent = false,  bool untilNotExistParent = false } );
/// 只设置父 Scope 存储数据,不影响自身
T setParentStoredData<T>(dynamic key, T data, { bool syncParent = false,  bool untilNotExistParent = false });
/// 获取存储的数据
/// 如果没有找到对应数据,可以设置 `fromParentIfNotExist = true` 从父 Scope 中
/// 获取对应 Key 下的数据,如果存在父 Scope 的话;如果父 Scope 仍然不存在数据,可以设置
/// `fromParentUntilNotExist = true`,如此会一直向上查找,直到找数据或已到达顶级 Scope.
/// * `untilNotExistParent` 只在 `fromParentIfNotExist = true` 下才生效.
/// 但是如果自身对应 Key 下存在数据,但是类型不匹配的话,会直接返回 `null`.
T getStoredData<T>(dynamic key, { bool fromParentIfNotExist = false, bool untilNotExistParent = false });
/// 重置存储所用的全部数据
/// * 只会重置自身存储的数据,不影响父 Scope 中的数据
void resetStoredData();

详细见使用样例

1.0.0 #

  • 上传至 pub 库

1.0.1 #

  • 完善 time 类

1.0.2 #

  • 修改 time parse 关于时区的问题

1.0.8 #

  • 新增 intEachList 方法,直接返回 List 类型结果

1.0.9 #

  • 新增 Scope 类,实现消息的传递、限定作用域的功能

1.1.0 #

  • 修复 Scope 包名路径的问题

1.1.1 #

  • 调整代码格式

1.1.2 #

  • 调整说明

1.1.3 #

  • 缩短说明

1.1.4 #

  • 新增同步代理监管

1.1.5 #

  • Scope 新增向上发布消息方法

1.1.6 #

  • 新增转换对象类型方法

1.1.7 #

  • Scope 新增存储数据方法 StoredData
  • Scope.rootScope 不能成为其他 Scope 的子 Scope

1.1.8 #

  • Scope 新增分发同代消息方法
  • Scope 新增分发一次性同代消息方法
  • Scope 新增向指定 id 的 Scope 分发消息方法

1.1.9 #

  • 修复 GeneralScope 的 scopeId 只能是字符串类型的问题,现在其可以指定为 dynamic 类型了

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  quicklibs: ^1.1.9

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:quicklibs/quicklibs.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
62
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
81
Learn more about scoring.

We analyzed this package on Nov 20, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.6.1
  • pana: 0.12.21

Platforms

Detected platforms: Flutter, web, other

No platform restriction found in primary library package:quicklibs/quicklibs.dart.

Health suggestions

Format lib/src/converts/convert_list.dart.

Run dartfmt to format lib/src/converts/convert_list.dart.

Format lib/src/converts/convert_obj.dart.

Run dartfmt to format lib/src/converts/convert_obj.dart.

Format lib/src/iterators/each.dart.

Run dartfmt to format lib/src/iterators/each.dart.

Fix additional 4 files with analysis or formatting issues.

Additional issues in the following files:

  • lib/src/scope/scope.dart (Run dartfmt to format lib/src/scope/scope.dart.)
  • lib/src/time/time.dart (Run dartfmt to format lib/src/time/time.dart.)
  • lib/src/time/time_format.dart (Run dartfmt to format lib/src/time/time_format.dart.)
  • lib/src/time/time_measure.dart (Run dartfmt to format lib/src/time/time_measure.dart.)

Maintenance suggestions

Maintain an example.

None of the files in the package's example/ directory matches known example patterns.

Common filename patterns include main.dart, example.dart, and quicklibs.dart. Packages with multiple examples should provide example/README.md.

For more information see the pub package layout conventions.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.2.0 <3.0.0