基于 Getx
实现的 MVVM
在原生的iOS、Android中我们已经习惯了使用MVVM取代MVC,来实现业务页面,这样结构更加清晰,也便于管理和功能扩展。在Flutter通过Getx来实现MVVM,如播放器的首页的实现,简化之后的代码如下。
View
的实现:在View
中实例化一个HomeController
并交给 Get
, build
方法中返回一个由GetBuilder <HomeController>( builder: (controller) {return ......;}
包裹的子widget,子widget的显示的数据有HomeController
调用update()
后来更新。但是需要注意的是,这里的HomeController
在退出本页面后不会主动销毁,如需要销毁,在dispose()
函数中调用Get.delete<HomeController>();
即可。
1 | class HomeView extends StatefulWidget { |
Model
主要用来保存网络请求的数据、记录页面widget的状态等
1 | class HomeState { |
ViewModel
HomeController
继承GetxController
来充当ViewModel
的角色,一般会在重写的父类onReady()
方法中发送物流异步请求,拿到数据后再调用update()
就会更新 GetBuilder <HomeController>( builder: (controller) {return ......;}
中的子Widget显示。
1 | class HomeController extends GetxController { |
HomeController
的实现覆盖的Widget范围可以更小,这样在调用update()
时需要更新的Widget也少一些,减少大面积的Widget更新,一定程度上提升页面流畅度,特别适合于比较复杂的页面。
换主题只需要这4步就能实现
第一步:定义好主题显示的数据,如
light
和dark
。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44///白天模式
static ThemeData lightTheme = ThemeData.light().copyWith(
primaryColor: const Color(0xffffffff),
splashColor: Colors.white,
highlightColor: Colors.white,
appBarTheme: const AppBarTheme(
systemOverlayStyle: SystemUiOverlayStyle.dark,
elevation: 0,
backgroundColor: Color(0xffffffff),
iconTheme: IconThemeData(color: Colors.black,size: 20),
titleTextStyle: TextStyle(
fontSize: 15,
color: Color(0xFF2d2d2d),
),
centerTitle: true,
),
scaffoldBackgroundColor: const Color(0xffF6F8F9),
backgroundColor: const Color(0xffF6F8F9),
dividerColor: const Color(0xffF6F8F9),
);
///夜间模式
static ThemeData darkTheme = ThemeData.dark().copyWith(
primaryColor: ThemeData.dark().primaryColor,
splashColor: ThemeData.dark().splashColor,
highlightColor: Colors.black,
appBarTheme: AppBarTheme(
systemOverlayStyle: SystemUiOverlayStyle.light,
elevation: 0,
backgroundColor: ThemeData.dark().cardColor,
iconTheme: const IconThemeData(color: Colors.white, size: 20),
titleTextStyle: const TextStyle(
fontSize: 15,
color: Color(0xFFeeeeee),
),
centerTitle: true,
),
scaffoldBackgroundColor: ThemeData.dark().scaffoldBackgroundColor,
backgroundColor: Colors.black,
iconTheme: const IconThemeData(
color: Colors.blue,
),
dividerColor: ThemeData.dark().dividerColor,
);在入口的Widget,即
runApp(const MyApp());
的MyApp
的GetMaterialApp
配置好上面声明的lightTheme
和darkTheme
。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Widget build(BuildContext context) {
return GetMaterialApp(
theme: ThemeConfig.lightTheme,
darkTheme: ThemeConfig.darkTheme,
);
}
}修改页面中需要更新的地方,如背景颜色、文字颜色等。
1
2
3Container(
color: Get.theme.primaryColor,
)手动触发切换
1
2
3
4
5
6
7GestureDetector(
onTap: () {
Get.changeThemeMode(Get.isDarkMode ? ThemeMode.light : ThemeMode.dark);
Future.delayed(Duration(milliseconds: 250), () {
Get.forceAppUpdate();
});
}}跟随系统变化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class AppLifeCycleDelegate with WidgetsBindingObserver {
static final AppLifeCycleDelegate _appLifeCycleDelegate =
AppLifeCycleDelegate._inital();
AppLifeCycleDelegate._inital() {
WidgetsBinding.instance?.addObserver(this);
}
factory AppLifeCycleDelegate() {
return _appLifeCycleDelegate;
}
void didChangePlatformBrightness() {
super.didChangePlatformBrightness();
Get.forceAppUpdate();
}
}在
main()
添加WidgetsFlutterBinding.ensureInitialized();
小结:以上实现是简化后的代码,具体实现在gtihub有详细实现。
欢迎关注公众号:flutter_todo,有更多技术干货和学习资源教程分享。