Flutter 高级:深入状态管理、自定义绘制与原生通信
【摘要】 在前两篇中,我们掌握了 Flutter 的基础和常用进阶技能。本文将继续深入,介绍 Riverpod 状态管理、自定义绘制与动画、性能优化以及与原生平台通信,助你向 Flutter 高手迈进。 1. Riverpod:更灵活的状态管理Riverpod 是 Provider 的改进版,解决了依赖注入和测试的痛点。首先添加依赖:dependencies: flutter_riverpod: ^...
在前两篇中,我们掌握了 Flutter 的基础和常用进阶技能。本文将继续深入,介绍 Riverpod 状态管理、自定义绘制与动画、性能优化以及与原生平台通信,助你向 Flutter 高手迈进。
1. Riverpod:更灵活的状态管理
Riverpod 是 Provider 的改进版,解决了依赖注入和测试的痛点。首先添加依赖:
dependencies:
flutter_riverpod: ^2.4.0
定义一个简单的状态提供者:
final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) {
return CounterNotifier();
});
class CounterNotifier extends StateNotifier<int> {
CounterNotifier() : super(0);
void increment() => state++;
}
在应用根部包裹 ProviderScope:
void main() {
runApp(ProviderScope(child: MyApp()));
}
在组件中使用:
class CounterPage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return Scaffold(
body: Center(child: Text('计数:$count')),
floatingActionButton: FloatingActionButton(
onPressed: () => ref.read(counterProvider.notifier).increment(),
child: Icon(Icons.add),
),
);
}
}
2. 自定义绘制与动画
使用 CustomPainter 可以绘制任意图形,结合 AnimationController 实现动态效果。
class MyPainter extends CustomPainter {
final double progress;
MyPainter(this.progress);
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.blue
..strokeWidth = 4
..style = PaintingStyle.stroke;
final rect = Rect.fromLTWH(0, 0, size.width, size.height);
canvas.drawArc(rect, 0, 2 * 3.14 * progress, false, paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
配合动画控制器使用:
class AnimatedCircle extends StatefulWidget {
@override
_AnimatedCircleState createState() => _AnimatedCircleState();
}
class _AnimatedCircleState extends State<AnimatedCircle>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: Duration(seconds: 2),
)..repeat();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return CustomPaint(
painter: MyPainter(_controller.value),
size: Size(200, 200),
);
},
);
}
}
3. 性能优化技巧
- 使用 const 构造函数:避免不必要的重建。
- 合理使用
ListView.builder:只构建可见项。 - 避免在 build 中执行耗时操作:使用
FutureBuilder或异步加载。 - 使用
RepaintBoundary:隔离重绘区域,减少绘制开销。 - 使用
const和final:提升内存效率。
4. 与原生平台通信
通过 MethodChannel 可以在 Flutter 与 Android/iOS 原生代码间传递消息。
Flutter 端:
class NativeBridge {
static const platform = MethodChannel('com.example.app/channel');
static Future<String> getBatteryLevel() async {
try {
final result = await platform.invokeMethod('getBatteryLevel');
return '电量:$result%';
} on PlatformException catch (e) {
return "获取失败:${e.message}";
}
}
}
Android 端(Kotlin):
class MainActivity : FlutterActivity() {
private val CHANNEL = "com.example.app/channel"
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
.setMethodCallHandler { call, result ->
if (call.method == "getBatteryLevel") {
val level = getBatteryLevel()
result.success(level)
} else {
result.notImplemented()
}
}
}
private fun getBatteryLevel(): Int {
// 获取电池电量的实际代码
return 80
}
}
5. 测试基础
Flutter 提供丰富的测试支持,从单元测试到 Widget 测试。
// 单元测试
test('计数器增加', () {
final counter = CounterNotifier();
counter.increment();
expect(counter.state, 1);
});
// Widget 测试
testWidgets('显示计数', (WidgetTester tester) async {
await tester.pumpWidget(ProviderScope(child: MyApp()));
expect(find.text('计数:0'), findsOneWidget);
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
expect(find.text('计数:1'), findsOneWidget);
});
6. 总结
掌握这些高级技能后,你将能构建性能优异、交互丰富且与原生深度集成的 Flutter 应用。继续探索官方文档和开源项目,不断精进!
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)