【Flutter】扩展 Map 对象功能
Dart 的 Map 对象虽然已经比较好用,但总有不满足的地方。
比如说,我想在 map 中取 key 为 'a' 的 int 类型数据,成功取到就用取到的值,取失败就用默认值,甚至如果是一个字符串类型的数值,我也希望能转成 int 给我。
要实现这些操作,如果不做点什么,就要写不少的判断什么的代码。如果一两个地方需要也就罢了,要是很多地方需要,那就有很多重复的代码了。
好在 dart 为我们提供了 extension
关键字,可以很方便的对现有类型进行功能扩展。废话不多说了,直接上代码,抛砖引玉,不喜勿喷!
import 'dart:convert';
import 'utils.dart';
/// Map 扩展
extension MapExtension on Map {
/// 取对象
_Set<Object?> get o => _Set((key) => key == null ? null : this[key]);
/// 取字符串
_Set<String> get s => _Set((key) => getString(key));
/// 取整数
_Set<int> get i => _Set<int>((key) => getInt(key));
/// 取浮点数
_Set<double> get f => _Set<double>((key) => getFloat(key));
/// 取日期时间
_Set<DateTime?> get d => _Set<DateTime?>((key) => getDateTime(key));
/// 取列表
_Set<List<dynamic>> get list => _Set<List<dynamic>>((key) => getList(key, (item) => item));
/// 获取字符串
String getString(final String? key, [final String defaultValue = '']) {
if (key == null) return defaultValue;
var _v = this[key];
if (_v == null) return defaultValue;
if (_v is String) return _v;
return "$_v";
}
/// 获取整数
int getInt(final String? key, [final int defaultValue = 0]) {
if (key == null) return defaultValue;
var _v = this[key];
if (_v == null) return defaultValue;
if (_v is int) return _v;
return Utils.toInt("$_v", 0);
}
/// 获取浮点数
double getFloat(final String? key, [final double defaultValue = 0.0]) {
if (key == null) return defaultValue;
return Utils.toFloat(this[key], defaultValue);
}
/// 获取时间
DateTime? getDateTime(final String? key, [final DateTime? defaultValue]) {
if (key == null) return defaultValue;
Object? v = this[key];
if (v == null) return defaultValue;
if (v is DateTime) return v;
if (v is int) return DateTime.fromMillisecondsSinceEpoch(v);
return DateUtil.toDateTime("$v", defaultValue);
}
/// 获取列表
/// [initClassCallback] - 根据item生成[T]类实例
List<T> getList<T>(final String? key, T Function(dynamic item)? initClassCallback) {
List<T> items = [];
if (key == null) return items;
Object? _items = this[key];
if (_items != null && (_items is List) && initClassCallback != null) {
for (var item in _items) {
items.add(initClassCallback(item));
}
}
return items;
}
/// 转为 JSON 字符串
String toJson() {
return const JsonEncoder().convert(this);
}
/// Json 对象转为 Map
static Map fromJson(final String data) {
return const JsonDecoder().convert(data);
}
}
class _Set<T> {
final T Function(String? key) onGetData;
_Set(this.onGetData);
T operator [](final String? key) {
return onGetData(key);
}
}
在将上面的代码保存后在任意文件中引入后,就可以这样使用了:
Map v = {'a': '123', 'b': '456', 'c': 666, 'items': ['a', 'b', 'c', 1, 2, 3] };
print(v.s['a']);
print(v.i['b']);
print(v.s['c']);
print(v.getList<Stirng>('items', (e) => e.toString()));