【Flutter开发】搬砖技巧扩展操作符“...” Dart 在 2.3 引入了 扩展操作符(...)和 空感知扩展操作
在线编程
DartPad
配置相关
开启 Linter 规则
在 flutter 工程的根路径下添加名为 analysis_options.yaml
的文件,即可配置静态分析的相关规则
具体配置可参考:github.com/jonataslaw/…
编码相关
避空运算符
Dart 提供了一系列方便的运算符用于处理可能会为空值的变量。其中一个是 ??=
赋值运算符,仅当该变量为空值时才为其赋值:
int? a; // = null
a ??= 3;
print(a); // <-- Prints 3.
a ??= 5;
print(a); // <-- Still prints 3.
另外一个避空运算符是 ??
,如果该运算符左边的表达式返回的是空值,则会计算并返回右边的表达式。
print(1 ?? 3); // <-- Prints 1.
print(null ?? 12); // <-- Prints 12.
初始化列表
有时,当你在实现构造函数时,您需要在构造函数体执行之前进行一些初始化。例如,final 修饰的字段必须在构造函数体执行之前赋值。在初始化列表中执行此操作,该列表位于构造函数的签名与其函数体之间:
Point.fromJson(Map<String, num> json)
: x = json['x'],
y = json['y'] {
print('In Point.fromJson(): ($x, $y)');
}
初始化列表也是放置断言的便利位置,它仅会在开发期间运行:
NonNegativePoint(this.x, this.y)
: assert(x >= 0),
assert(y >= 0) {
print('I just made a NonNegativePoint: ($x, $y)');
}
扩展操作符“...”
Dart 在 2.3 引入了 扩展操作符(...
)和 空感知扩展操作符(...?
),它们提供了一种将多个元素插入集合的简洁方法。
例如,你可以使用扩展操作符(...
)将一个 List 中的所有元素插入到另一个 List 中:
var list = [1, 2, 3];
var list2 = [0, ...list];
assert(list2.length == 4);
如果扩展操作符右边可能为 null ,你可以使用 null-aware 扩展操作符(...?
)来避免产生异常:
var list;
var list2 = [0, ...?list];
assert(list2.length == 1);
可以查阅扩展操作符建议获取更多关于如何使用扩展操作符的信息。
集合中的 if
Dart 还同时引入了 集合中的 if 和 集合中的 for 操作,在构建集合时,可以使用条件判断 (if
) 和循环 (for
)。
下面示例是使用 集合中的 if 来创建一个 List 的示例,它可能包含 3 个或 4 个元素:
var nav = [
'Home',
'Furniture',
'Plants',
if (promoActive) 'Outlet'
];
懒加载
In the following example, if the temperature
variable is never used, then the expensive _readThermometer()
function is never called:
// This is the program's only call to _readThermometer().
late String temperature = _readThermometer(); // Lazily initialized.
格式化json字符串
String prettyJsonString(dynamic json) {
JsonEncoder encoder = new JsonEncoder.withIndent(' ');
String jsonString = encoder.convert(json);
return jsonString;
}
dynamic 转字符串
static Object toEncodableFallback(dynamic object) {
return object.toString();
}
static String stringifyMessage(dynamic message) {
final finalMessage = message is Function ? message() : message;
if (finalMessage is Map || finalMessage is Iterable) {
var encoder = JsonEncoder.withIndent(' ', toEncodableFallback);
return encoder.convert(finalMessage);
} else {
return finalMessage.toString();
}
}
删除集合中的空对象
import 'dart:core';
Map<String, dynamic> removeNullsFromMap(Map<String, dynamic> json) => json
..removeWhere((String key, dynamic value) => value == null)
..map<String, dynamic>((key, value) => MapEntry(key, removeNulls(value)));
List removeNullsFromList(List list) => list
..removeWhere((value) => value == null)
..map(removeNulls).toList();
dynamic removeNulls(dynamic e) => (e is List)
? removeNullsFromList(e)
: (e is Map ? removeNullsFromMap(e as Map<String, dynamic>) : e);
extension ListExtension on List {
List removeNulls() => removeNullsFromList(this);
}
extension MapExtension on Map {
Map removeNulls() => removeNullsFromMap(this as Map<String, dynamic>);
}
疑难杂症
GestureDetector 的交互范围
因为在开发中,都是高度自定义的UI组件,类似按钮,基本上都是通过包裹 GestureDetector
来实现
但问题是,包裹后的组件总是很难点击到(触发 onTap 等事件),特别是“文字按钮”
在实践中发现,可以通过【设置背景色】来解决
—— 如果不需要有色背景,用透明背景Colors.transparent
也是有效的
GestureDetector(
child: Container(
width: 67,
height: 40,
alignment: Alignment.center,
color: Colors.transparent, // <= 可以体验下 有或没有这行代码的效果
child: Text('取消'),
),
onTap: () => print('onTap'),
)
TextField 中文字过多时 内容会被裁切
-
内容不多时 可以正常显示
-
内容过多时 文字底部会被裁切
解决方法:
修改 TextField.decoration.contentPadding
属性,完整示例如下:
Widget buildSearchBarTextField() {
return TextField(
autofocus: false,
minLines: 1,
textInputAction: TextInputAction.search,
controller: textEditingController,
focusNode: focusNode,
textAlignVertical: TextAlignVertical.top, // 新加代码
style: TextStyle(color: Color(0xFF1F1F1F), fontWeight: FontWeight.w400, fontSize: 15),
decoration: InputDecoration(
hintText: '输入字词、成语、诗词',
hintStyle: TextStyle(color: Color(0xFF8E8F85)),
hintMaxLines: 1,
border: InputBorder.none,
isCollapsed: false,
contentPadding: const EdgeInsets.only(bottom: 10), // 新加代码
),
onChanged: onChangedTextField,
onSubmitted: onSubmittedTextField,
).bhk_expanded();
}
效果如下:
参考文档
转载自:https://juejin.cn/post/6995880893113958408