Flutter类切换插件class_switch的使用
Flutter类切换插件class_switch的使用
class_switch
可以让你在类实例的所有子类上进行切换,或者在多个基类实例的所有可能组合上进行切换。通过使用 class_switch_generator
库和来自 class_switch
的注解,你可以生成函数和混合(mixins)来执行可定制的类型安全切换。它与 bloc 搭配使用非常棒,可以帮助你摆脱事件和状态处理的样板代码。请参阅下面的“示例与 bloc 结合使用”部分以了解更多信息。
class_switch
库具体包含用于 class_switch_generator
库的注解,以便生成可以对类进行切换的代码。
如何使用
- 将
class_switch
添加为普通依赖项。 - 将
class_switch_generator
添加为开发依赖项。 - 使用
[@ClassSwitch](/user/ClassSwitch)
注解类。 - 确保注解参数中提供的类的子类与注解所在的文件在同一文件中或通过
part
语句包含。 - 在包含注解类的文件中包含
part 'YOUR_FILE_NAME.g.dart';
。 - 运行
pub run build_runner watch
。 - 现在你可以通过使用生成的
$switchXXYY
函数来切换注解类。
class_switch的优点
使用 class_switch
的一些优点包括:
- 接近于能够对注解类的所有子类进行
switch()
的 API。 - 编译时保证(当运行
pub run build_runner watch
时),所有可能的子类都被class_switch
覆盖。 - 可自动补全的类切换语句,所有情况都已准备好填充。
- 提供了很好的自动补全体验的切换器混合类:添加一个新的子类型后,可以在任何实现该混合的类中自动完成新子类型的缺失函数。
- 可以切换多个不同的基类,生成的切换器具有针对每种可能的子类型组合的 case 语句。与 bloc 库结合使用时非常有用!
- 通过注解选项提供了高度可定制的代码生成,有多种不同的可配置的领域特定语言(DSL),以匹配你的用法并使生成的代码尽可能易读。
重要注意事项
- 当注解一个基类时,其所有子类必须在同一文件中或通过
part
语句包含在注解文件中,否则class_switcher
将找不到这些子类,并且如果提供未知的子类,则生成的代码将在运行时抛出错误。
示例用法
ClassSwitch
将为名为 BaseClass
并用 [@ClassSwitch](/user/ClassSwitch)()
注解的类生成以下内容(当使用默认模式 [DSL_MODE.CLASS_WRAPPER] 时):
全局 $switch
函数
一个全局的 $switchBaseClass
函数,该函数接受 BaseClass
的一个实例并返回一个可调用的类,可以为其每个直接子类提供 case 函数以执行切换:
[@ClassSwitch](/user/ClassSwitch)()
abstract class BaseClass {}
class A extends BaseClass {}
class B extends BaseClass {}
// 生成的函数可以这样使用:
var x = $switchBaseClass(A())(
(a) => 1, //
(b) => 2);
assert(x == 1);
// 通过先输入 `.call` 或 `.cases` 来帮助你自动补全:
x = $switchBaseClass(A()).cases(
(a) => 1, //
(b) => 2);
assert(x == 1);
扩展方法
在注解类上生成一个扩展方法,名为 .$switch
,当不提供其他类作为参数时,将使用该实例进行切换。当提供其他类时,则需要同时提供所有实例。
[@ClassSwitch](/user/ClassSwitch)()
abstract class BaseClass {}
class A extends BaseClass {}
class B extends BaseClass {}
// 生成的扩展方法可以这样使用:
BaseClass anUnknownSubType = A();
var x = anUnknownSubType.$switch(
(a) => 1, //
(b) => 2);
assert(x == 1);
切换器混合类
生成一个抽象的切换器混合类,该类包含:
- 对于同一文件中找到的每个可能的子类的抽象子类方法。
- 一个
$switch
方法,该方法接受注解类的一个实例并根据实例的类型调用适当的子类方法。
[@ClassSwitch](/user/ClassSwitch)()
abstract class BaseClass {}
class A extends BaseClass {}
class B extends BaseClass {}
// 生成的混合类可以这样使用:
class MySwitcher extends _$BaseClassSwitcher<int>{
[@override](/user/override)
int a(A a) => 1;
[@override](/user/override)
int b(B b) => 2;
};
assert(MySwitcher().$switch(A()) == 1);
带有默认值的切换器混合类
生成一个抽象的带有默认值的切换器混合类,该类包含:
- 一个允许为所有未覆盖子类方法的类型设置默认值的抽象默认方法。
- 对于同一文件中找到的每个可能的子类的子类方法,除非被覆盖,否则将返回默认方法的结果。
[@ClassSwitch](/user/ClassSwitch)()
abstract class BaseClass {}
class A extends BaseClass {}
class B extends BaseClass {}
// 生成的混合类可以这样使用:
class MySwitcher extends _$BaseClassSwitcherWithDefault<int>{
[@override](/user/override)
int defaultValue() => 1;
[@override](/user/override)
int b(B b) => 2;
};
assert(MySwitcher().$switch(A()) == 1);
切换多个基类
上述所有功能都可以指定要切换的多个不同的基类。这对于与 bloc 一起工作非常有用!
示例与 bloc 结合使用
下面的示例展示了如何将 class_switch
与 bloc 库结合使用。然而,多基类切换在任何类似的情况下也可以不使用 bloc 直接使用。
abstract class BlocState {}
class StateA extends BlocState {}
class StateB extends BlocState {}
abstract class BlocEvent {}
class EventA extends BlocEvent {}
class EventB extends BlocEvent {}
// 生成的混合类可以这样使用:
[@ClassSwitch](/user/ClassSwitch)(classes:[BlocState, BlocEvent])
class MyBloc extends Bloc<BlocEvent, BlocState> with _$MyBlocSwitcher<BlocState> {
[@override](/user/override)
Stream<BlocState> mapEventToState(
BlocEvent event,
) async* {
yield this.$switch(this.state, event);
}
[@override](/user/override)
BlocState stateAEventA(StateA stateA, EventA eventA) => stateA;
[@override](/user/override)
BlocState stateAEventB(StateA stateA, EventB eventB) => stateA;
[@override](/user/override)
BlocState stateBEventA(StateB stateB, EventA eventA) => stateB;
[@override](/user/override)
BlocState stateBEventB(StateB stateB, EventB eventB) => stateB;
}
// 或者直接用作函数:
var r = $switchMyBloc(StateA(), EventA()).cases(
(StateA stateA, EventA eventA) => 'a a',
(StateA stateA, EventB eventB) => 'a b',
(StateB stateB, EventA eventA) => 'b a',
(StateB stateB, EventB eventB) => 'b b',
);
assert(r == 'a a');
更多关于Flutter类切换插件class_switch的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter类切换插件class_switch的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,我可以为你提供一个关于如何在Flutter中使用class_switch
插件(假设这是一个假想的插件名称,因为Flutter社区中并没有一个直接名为class_switch
的官方或广泛使用的插件)的示例代码。不过,由于class_switch
并非真实存在的插件,我将基于插件可能的功能——即在Flutter应用中切换不同的页面或类——来编写一个示例。
在实际应用中,Flutter提供了多种方式来切换页面或类,最常见的是使用Navigator
。下面是一个简单的示例,展示如何在Flutter中通过Navigator
在不同的页面(或类)之间切换。
示例代码
首先,我们需要创建两个简单的页面(或类),例如HomePage
和SecondPage
。
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Class Switch Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home Page'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
// 使用Navigator跳转到SecondPage
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondPage()),
);
},
child: Text('Go to Second Page'),
),
),
);
}
}
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Second Page'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
// 使用Navigator返回HomePage
Navigator.pop(context);
},
child: Text('Go Back'),
),
),
);
}
}
解释
-
MyApp:这是应用的根部件,它使用
MaterialApp
作为顶级部件,设置了应用的标题和主题,并将HomePage
设为初始页面。 -
HomePage:这是应用的第一个页面。它包含一个
AppBar
和一个居中的ElevatedButton
。当按钮被点击时,使用Navigator.push
方法将一个新的页面(SecondPage
)推送到导航栈上。 -
SecondPage:这是第二个页面。它也包含一个
AppBar
和一个居中的ElevatedButton
。当按钮被点击时,使用Navigator.pop
方法从导航栈中弹出当前页面,返回到上一个页面(HomePage
)。
注意
- 在这个示例中,我们并没有使用名为
class_switch
的插件,因为这样的插件并不存在。相反,我们使用了Flutter内置的Navigator
来实现页面(或类)之间的切换。 - 如果你确实在寻找一个特定的插件来实现类似的功能,你可能需要查看Flutter的插件库(pub.dev)来找到符合你需求的插件。然后,你可以根据该插件的文档和示例代码来集成和使用它。
希望这个示例能够帮助你理解如何在Flutter中实现页面(或类)之间的切换!