图片发布
看看能不能发布图片
看看能不能发布图片
在 Flutter 应用开发中,状态管理是一个核心挑战。随着应用复杂度的提升,如何高效地管理状态、处理依赖注入以及实现路由导航,成为了开发者必须面对的问题。本文将深入探讨 GetX 框架的特点、基础使用以及高级应用场景,帮助开发者全面掌握这一框架。
GetX集成了状态管理、依赖注入和路由管理三大核心功能。与其他状态管理方案相比,GetX的最大优势在于其简洁的语法和极低的学习曲线,同时保持了高性能和强大的功能。使用 GetX,开发者可以用更少的代码实现更复杂的功能,大大提高开发效率,很适合在下面的几个场景中使用:
getx采用了响应式的编程的思想Obx避免不必要的UI刷新,只有真正需要更新的widget的才会被重建,从而提高应用的性能,它比其他传统的状态管理方案占用的内存更小,响应速度更快;
import 'package:flutter/material.dart';
import 'package:get/get.dart';
// 创建一个控制器类,继承自GetxController
class CounterController extends GetxController{
// 创建一个响应式变量,初始值为0// 通过obs后缀,我们将普通变量转换为可观察的响应式变量var count = 0.obs;
// 增加计数的方法void increment() {
count.value++;
}
}
void main() {
// 注册控制器,使其在应用中全局可用Get.put(CounterController());
runApp(MyApp());
}
class MyApp extends StatelessWidget{
@overrideWidget build(BuildContext context) {
return GetMaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('GetX Counter')),
body: Center(
// 使用Obx包裹需要监听状态变化的widget,// 当里面的响应式变量发生变化时,Obx 会自动更新对应widget的内容child: Obx(() => Text(
'Count: ${Get.find<CounterController>().count}',
style: TextStyle(fontSize: 24),
)),
),
floatingActionButton: FloatingActionButton(
onPressed: () => Get.find<CounterController>().increment(),
child: Icon(Icons.add),
),
),
);
}
}
本系列文章共有三篇,计划分别从Flutter、Dart、工具三个方面介绍,快速形成对Flutter开发的一个综合概念。
本文主要介绍Flutter相关知识。
Flutter语言使用 Dart,开发IDE使用VSCode、Android Studio 或 IntelliJ IDEA,个人推荐使用VSCode。
Flutter是由Google开发的开源移动应用开发框架,用于快速构建高性能、高保真度的跨平台移动应用。Flutter支持同一套代码在 iOS、Android、Web、桌面应用等多个平台上运行,使用自带的 Skia 图形引擎,可以直接绘制 UI 组件,这使得 Flutter 应用在性能方面表现出色,滚动流畅,响应迅速(目前正在使用 Impeller 替换 Skia)。
看一眼有个印象即可。
参考资料
Flutter的渲染机制由三棵树组成:Widget Tree、Element Tree、Render Tree(渲染树)。
所有Widget组成Widget Tree。
通过调用Widget的createElement()方法,创建Element Tree,Wdiget Tree与Element Tree是一一对应的。
每个Element调用 createRenderObject()形成Render Tree,Render Tree负责渲染,注意Render Tree与Elemeng Tree并不是一一对应的,而是为最后渲染做准备。
// StatelessWidget 定义
abstract class StatelessWidget extends Widget {
const StatelessWidget({ super.key });
@override
StatelessElement createElement() => StatelessElement(this);
// 核心是 build 方法
@protected
Widget build(BuildContext context);
}
// 示例,Echo widget,核心是build方法构建UI
class Echo extends StatelessWidget {
const Echo({
Key? key,
required this.text,
this.backgroundColor = Colors.grey, //默认为灰色
}):super(key:key);
final String text;
final Color backgroundColor;
@override
Widget build(BuildContext context) {
return Center(
child: Container(
color: backgroundColor,
child: Text(text),
),
);
}
}
// 在子树中获取父级widget的一个示例:
class ContextRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Context测试"),
),
body: Container(
child: Builder(builder: (context) {
// 在 widget 树中向上查找最近的父级`Scaffold` widget
Scaffold scaffold = context.findAncestorWidgetOfExactType<Scaffold>();
// 直接返回 AppBar的title, 此处实际上是Text("Context测试")
return (scaffold.appBar as AppBar).title;
}),
),
);
}
}
StatefulWidget的核心就是有状态,可以修改重绘UI。
StatefulWidget重写了createElement方法,返回的是StatefulElement,StatefulElement可能会多次调用createState()来创建对象。
createState(),创建状态,修改UI必须通过修改状态来实现,一个StatefulElement对应一个State实例。
abstract class StatefulWidget extends Widget {const StatefulWidget({ Key key }) : super(key: key);
@override
StatefulElement createElement() => StatefulElement(this);
@protected
State createState();
}
添加插件
tutorial_coach_mark: 1.2.11
import 'package:flutter/material.dart';
import 'package:tutorial_coach_mark/tutorial_coach_mark.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget{
const MyApp({super.key});
@override
Widget build(BuildContext context) => MaterialApp(home: const HomePage());
}
class HomePage extends StatefulWidget{
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage>{
late TutorialCoachMark tutorial;
final _keyAdd = GlobalKey(),
_keySearch = GlobalKey(),
_keyProfile = GlobalKey();
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) => _showTutorial());
}
void _showTutorial() {
tutorial = TutorialCoachMark(
targets: _createTargets(),
colorShadow: Colors.black54,
opacityShadow: 0.7,
paddingFocus: 8,
textSkip: '跳过',
onFinish: () => print('完成'),
onSkip: () {
print('跳过');
return true;
},
)..show(context: context);
}
List<TargetFocus> _createTargets() => [
TargetFocus(
identify: 'add',
keyTarget: _keyAdd,
contents: [
TargetContent(
align: ContentAlign.bottom,
builder: (_, __) =>
const Text('点击这里添加任务', style: TextStyle(color: Colors.white)),
)
],
),
TargetFocus(
identify: 'search',
keyTarget: _keySearch,
contents: [
TargetContent(
align: ContentAlign.top,
builder: (_, __) =>
const Text('快速搜索内容', style: TextStyle(color: Colors.white)),
)
],
),
TargetFocus(
identify: 'profile',
keyTarget: _keyProfile,
contents: [
TargetContent(
align: ContentAlign.left,
builder: (_, __) =>
const Text('进入个人中心', style: TextStyle(color: Colors.white)),
)
],
),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('局部高亮教程')),
floatingActionButton: FloatingActionButton(
key: _keyProfile,
onPressed: () => _showTutorial(),
child: const Icon(Icons.person),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
key: _keyAdd,
onPressed: () {},
child: const Text('添加'),
),
const SizedBox(height: 20),
ElevatedButton(
key: _keySearch,
onPressed: () {},
child: const Text('搜索'),
),
const SizedBox(height: 40),
OutlinedButton(
onPressed: _showTutorial,
child: const Text('再看一次'),
),
],
),
),
);
}
}