Flutter 高级:深入状态管理、自定义绘制与原生通信

举报
yd_232225224 发表于 2026/09/03 13:57:21 2026/09/03
【摘要】 在前两篇中,我们掌握了 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)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。