昨天看群友发了一张这样代码图: 里面有两点让我感到很疑惑:AsyncData(:final value)
是什么东西?if (value.data?.topics case final topic?)
又是个啥?这真的还是dart代码吗? 于是上网一查,原来还真有这样的东西,该更新一下大脑补一下课了。
if-case-when
上面的是官方的解释,嗯...我们还是自己动手试试吧。
在以前,如果判断一个值是否为数组且该数组长度为2且该数组里的元素都大于0,可以这样写:
javascript
void checkTypeOld(dynamic value) {
if (value is List && value.length == 2 && value.every((e) => e > 0)) {
print('value.type is list and value.length == 2 and all element of value is bigger than 0');
}
}
用dart3则可以这样:
csharp
void checkTypeNew(dynamic value) {
if (value case [int x, int y] when x > 0 && y > 0) {
print('value.type is list and value.length == 2 and all element of value is bigger than 0');
}
}
看起来dart3更简洁?它一句case [int x, int y]
就做了前两个判断同时取值出来方便下一步计算。
那么能不能再更简洁一点呢?假设这里要判断的长度不是2,而是20,[int x, int y...]
这样赋值也太累了。答案当然是可以的。
csharp
void checkTypeNew(dynamic value) {
if (value case List(length: 20) when value.every((e) => e > 0)) {
print('value.type is list and value.length == 20 and all element of value is bigger than 0');
}
}
List()
能用的不仅有length
,还有isEmpty
,first
等,只要类型里有写getter方法的都能用。
AsyncData(:final value)
AsyncData是riverpod自定义的class,继承于AsyncValue。通过观察上述的代码能够判断出hotList应该是一个AsyncValue类型的变量,然后在这里通过switch判断具体的类型来显示不同的UI。明白了代码的作用后就该看看那个:final value
是啥了。
这里我跟着riverpod的教程弄了一下,其中Activity是自定义的类,里面只有一个final String key
。
scss
Consumer(
builder: (context, ref, child) {
final AsyncValue<Activity> activity = ref.watch(activityProvider);
return Center(
child: switch (activity) {
AsyncData(:Activity value) => Text('Activity: ${value.key}'),
AsyncError() => const Text('Oops, something unexpected happened'),
_ => const CircularProgressIndicator(),
},
);
},
);
这样就可以明确看出activity
和value
的类型,那么根据AsyncData的源码,不难看出:Activity value
就是取出AsyncData里的值的意思。
那么如果我不喜欢value
,可以把它改成item
或者其他的变量吗?
并不可以!会报出以下错误The getter 'item' isn't defined for the type 'AsyncData<Activity>'
.
又是getter!再深入进去看一眼AsyncValue的实现,发现它其实是这样的:
综上所述,如果想要使用:final value
这种语法,也是要求类有提供getter方法。那么我自己也实现一个试试。
dart
class Item {
Item._(this._id);
factory Item.from(String id) => Item._(id);
String _id;
String get id => _id;
set id(String value) {
if (value != id) {
_id = value;
}
}
}
把它也加到上面判断类型的函数里那就会是这样:
csharp
void checkTypeNew(dynamic value) {
if (value case List(length: 20) when value.every((e) => e > 0)) {
print('value.type is list and value.length == 20 and all element of value is bigger than 0');
} else if (value case Item(:final id) when id.isNotEmpty) {
print('value.type is Item and value.id is not empty');
}
}
再把这堆if-else优化一下:
scss
void checkTypeNew(dynamic value) {
switch(value) {
case List(length: 20) when value.every((e) => e > 0):
print('value.type is list and value.length == 20 and all element of value is bigger than 0');
case Item(:final id) when id.isNotEmpty:
print('value.type is Item and value.id is not empty');
}
}
当然也可以这样写,连case都省略掉:
dart
String checkTypeNew(dynamic value) {
return switch (value) {
List(length: 20) when value.every((e) => e > 0) =>
'value.type is list and value.length == 20 and all element of value is bigger than 0',
Item(:final id) when id.isNotEmpty =>
'value.type is Item and value.id is not empty',
_ => 'undefined'
};
}
// 这样调用
print(checkTypeNew(***));
同时,括号里不仅可以获取一个getter,而是可以获取多个getter,以list为例:
vbnet
String checkTypeNew(dynamic value) {
return switch (value) {
List(length: 20, :final last)
when value.every((e) => e > 0) && last > 10 =>
'value.type is list and value.length == 20 and all element of value > 0 and last element > 10',
Item(:final id) when id.isNotEmpty =>
'value.type is Item and value.id is not empty',
String string when string.isNotEmpty =>
'value is String and value is not empty',
_ => 'undefined'
};
}
最后
这篇文章也只是一个抛砖引玉,我只知道这些东西该怎么用,并不知道这些东西的原理,只能感觉这些都是dart3改新swtich的时候改出来的新特性,具体原理要是能有高手补充一下原理就好了。 dart3这套新switch总是可以把代码写得更简洁,还蛮好用的,虽然不用也没问题,但是你都用flutter这种新玩意了,与时俱进学点新东西不是挺好的吗?