jskit
Flutter 常用工具包,包含网络请求封装、格式化与节流工具,以及一组轻量 UI 组件。
当前主入口为 lib/jskit.dart,公开导出:
- 网络层:
JSCore、DioUtil、JSBaseRequest - 工具类:
JsTools、FunctionExt - 扩展能力:时间/数字/邮箱/密码强度格式化
- 组件:
Vitrify、FrostedGlass、TurnBox、GradientBorder、AfterLayout、CustomBlurAppBar、KeepAliveWrapper
安装
按你的接入方式选择一种:
本地路径引用
dependencies:
jskit:
path: ../jskit-flutter
Git 引用
dependencies:
jskit:
git:
url: https://github.com/json1994/jskit-flutter.git
已发布到仓库时
dependencies:
jskit: ^0.1.9
导入:
import 'package:jskit/jskit.dart';
功能概览
1. 网络请求封装
适合后端返回结构固定为下面这种场景:
{
"code": 200,
"message": "success",
"total": 0,
"data": {}
}
JSBaseRequest 默认按这个结构读取 code、message、total、data。
2. 工具方法
JsTools.generateRandomColorJsTools.generateRandomStringJsTools.getMd5()JsTools.showSheetWidget()JsTools.showDropDownWidget()JsTools.textFieldConfig()JsTools.calculateCacheSize()JsTools.clearCache()JsTools.writeFile()
3. 扩展能力
num?.countFormatnum?.durationFormatnum?.formatFileSizeDateTime?.toYMDDateTime?.weekDateTime?.monthStrDateTime?.messageTime()String?.isEmailString?.checkPasswordStrength()Function.throttle()Function.throttleWithTimeout()Function.debounce()
4. UI 组件
Vitrify:毛玻璃容器,可配置颜色、透明度、圆角、blur 和动画FrostedGlass:简单毛玻璃背景层TurnBox:旋转动画组件GradientBorder:渐变描边AfterLayout:布局结束后拿到 render 信息CustomBlurAppBar:滚动时带模糊效果的 AppBarKeepAliveWrapper:列表/分页保活包装
快速开始
初始化网络层
await JSCore().init(
baseUrl: 'https://api.example.com',
hookRequest: (options) {
options.headers['token'] = 'your-token';
},
);
如果你已经有自己的 Dio 实例,也可以直接注入:
final dio = Dio(
BaseOptions(
baseUrl: 'https://api.example.com',
connectTimeout: const Duration(seconds: 10),
receiveTimeout: const Duration(seconds: 30),
),
);
await JSCore().init(dio: dio);
直接使用 DioUtil 发请求
final result = await DioUtil().request<Map<String, dynamic>>(
'/user/profile',
method: DioMethod.get,
parameters: {'id': 1001},
);
if (result.response != null) {
print(result.response);
}
自定义请求类
推荐业务中继承 JSBaseRequest,把接口定义收敛到请求对象里。
class UserEntity {
final int id;
final String name;
UserEntity({
required this.id,
required this.name,
});
factory UserEntity.fromJson(Map<String, dynamic> json) {
return UserEntity(
id: json['id'] as int,
name: json['name'] as String,
);
}
}
class UserDetailRequest
extends JSBaseRequest<UserEntity, Map<String, dynamic>> {
UserDetailRequest(int userId)
: super(
url: '/user/detail',
method: DioMethod.get,
parameters: {'id': userId},
fromJson: UserEntity.fromJson,
);
}
调用:
final response = await UserDetailRequest(1001).execute();
if (response.code == 200 && response.data != null) {
print(response.data!.name);
} else {
print(response.msg);
}
POST / PUT / PATCH 示例
class UpdateUserRequest
extends JSBaseRequest<Map<String, dynamic>, Map<String, dynamic>> {
UpdateUserRequest({
required int id,
required String name,
}) : super(
url: '/user/update',
method: DioMethod.put,
parameters: {'id': id},
data: {'name': name},
fromJson: (json) => json,
);
}
工具示例
数字与时间格式化
final count = 12500.countFormat; // 1.3w
final duration = 95.durationFormat; // 01:35
final fileSize = 1024 * 1024 * 2.4.formatFileSize; // 2.40M
final now = DateTime.now();
print(now.toYMD);
print(now.week);
print(now.monthStr);
字符串校验
final email = 'demo@example.com'.isEmail;
final strength = 'abc123!@#'.checkPasswordStrength();
节流与防抖
final onTap = () async {
print('submit');
};
final throttledTap = onTap.throttle();
final debouncedTap = onTap.debounce(timeout: 300);
弹窗工具
await JsTools.showSheetWidget(
context,
position: ModalPosition.bottom,
builder: (_) {
return Container(
height: 240,
color: Colors.white,
child: const Center(child: Text('bottom sheet')),
);
},
);
输入框键盘工具条
final focus1 = FocusNode();
final focus2 = FocusNode();
final config = JsTools.textFieldConfig(
nodes: [focus1, focus2],
doneString: '完成',
);
组件示例
Vitrify
Vitrify(
sigma: 12,
opacity: 0.3,
color: Colors.white,
radius: BorderRadius.circular(16),
child: Container(
padding: const EdgeInsets.all(16),
child: const Text('Glass Card'),
),
)
FrostedGlass
FrostedGlass(
blurX: 12,
blurY: 12,
opacity: 0.2,
child: Container(
height: 160,
alignment: Alignment.center,
child: const Text('Blur Background'),
),
)
TurnBox
final controller = TurnBoxController(false);
TurnBox(
turns: 3.1415926,
speed: 300,
controller: controller,
child: const Icon(Icons.expand_more),
)
// 展开
controller.forward(from: 0);
// 收起
controller.reverse(from: 1);
GradientBorder
GradientBorder(
isSelected: true,
borderWidth: 2,
borderRadius: 12,
gradientColors: const [
Colors.blue,
Colors.cyan,
Colors.green,
],
child: Container(
padding: const EdgeInsets.all(16),
child: const Text('Gradient Border'),
),
)
AfterLayout
AfterLayout(
callback: (render) {
print(render.size);
print(render.offset);
print(render.rect);
},
child: Container(
width: 100,
height: 60,
color: Colors.red,
),
)
KeepAliveWrapper
KeepAliveWrapper(
keepAlive: true,
child: ListView.builder(
itemCount: 20,
itemBuilder: (_, index) => ListTile(title: Text('$index')),
),
)
已知约定
JSBaseRequest默认成功条件是response['code'] == 200- 默认错误文案读取
response['message'] convert()只有在data is K时才会调用fromJsonTurnBox.turns当前直接作为Transform.rotate的角度值使用,不是“圈数”CustomBlurAppBar适合放在滚动页面场景中使用
开发与验证
本仓库当前已验证:
flutter analyze
flutter test
发布
flutter packages pub publish --server=https://pub.dartlang.org