logo
Flutter 入门

Flutter 高级主题

简介

深入探讨 Flutter 的高级应用场景,包括状态管理进阶、动画效果和自定义 Widget

状态管理进阶

在 Flutter 中,除了基本的 StatefulWidget,还有多种高级状态管理解决方案。

Provider

Provider 是 Flutter 官方推荐的状态管理方案之一:

// 定义数据模型
class Counter with ChangeNotifier {
  int _count = 0;
  int get count => _count;

  void increment() {
    _count++;
    notifyListeners();
  }
}

// 在根 Widget 中提供数据
void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => Counter(),
      child: MyApp(),
    ),
  );
}

// 在子 Widget 中使用数据
class CounterWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text(
      '${context.watch<Counter>().count}',
    );
  }
}

GetX

GetX 是一个轻量且强大的解决方案:

// 控制器
class CounterController extends GetxController {
  var count = 0.obs;

  void increment() => count++;
}

// 在页面中使用
class CounterPage extends StatelessWidget {
  final controller = Get.put(CounterController());

  @override
  Widget build(BuildContext context) {
    return Obx(() => Text('${controller.count}'));
  }
}

动画效果

Flutter 提供了丰富的动画支持,从简单的补间动画到复杂的自定义动画。

1. 基础动画

class AnimatedLogo extends StatefulWidget {
  @override
  _AnimatedLogoState createState() => _AnimatedLogoState();
}

class _AnimatedLogoState extends State<AnimatedLogo>
    with SingleTickerProviderStateMixin {
  late AnimationController controller;
  late Animation<double> animation;

  @override
  void initState() {
    super.initState();
    controller = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    );
    animation = CurvedAnimation(
      parent: controller,
      curve: Curves.easeInOut,
    );
    controller.repeat(reverse: true);
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: animation,
      builder: (context, child) {
        return Transform.scale(
          scale: animation.value,
          child: FlutterLogo(size: 100),
        );
      },
    );
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }
}

2. 隐式动画

class AnimatedContainer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return AnimatedContainer(
      duration: Duration(seconds: 1),
      curve: Curves.easeInOut,
      width: 200,
      height: 200,
      decoration: BoxDecoration(
        color: Colors.blue,
        borderRadius: BorderRadius.circular(20),
      ),
    );
  }
}

自定义 Widget

创建自定义 Widget 可以提高代码复用性和可维护性。

1. 自定义画布

class CustomPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.blue
      ..strokeWidth = 4
      ..style = PaintingStyle.stroke;

    final path = Path()
      ..moveTo(0, size.height / 2)
      ..quadraticBezierTo(
        size.width / 2,
        0,
        size.width,
        size.height / 2,
      );

    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}

2. 自定义手势

class CustomGestureDetector extends StatefulWidget {
  @override
  _CustomGestureDetectorState createState() => _CustomGestureDetectorState();
}

class _CustomGestureDetectorState extends State<CustomGestureDetector> {
  double _scale = 1.0;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onScaleUpdate: (details) {
        setState(() {
          _scale = details.scale;
        });
      },
      child: Transform.scale(
        scale: _scale,
        child: Container(
          width: 200,
          height: 200,
          color: Colors.blue,
        ),
      ),
    );
  }
}

平台集成

1. 平台特定代码

import 'dart:io' show Platform;

class PlatformCheck {
  static String getPlatformName() {
    if (Platform.isAndroid) {
      return 'Android';
    } else if (Platform.isIOS) {
      return 'iOS';
    }
    return 'Unknown';
  }
}

2. 平台通道

// 定义平台通道
static const platform = MethodChannel('samples.flutter.dev/battery');

// 调用原生方法
Future<void> getBatteryLevel() async {
  try {
    final int result = await platform.invokeMethod('getBatteryLevel');
    print('Battery level: $result%');
  } on PlatformException catch (e) {
    print('Failed to get battery level: ${e.message}');
  }
}

性能优化技巧

1. 构建优化

// 使用 const 构造函数
const MyWidget({
  Key? key,
  required this.title,
}) : super(key: key);

// 使用 RepaintBoundary 隔离重绘区域
RepaintBoundary(
  child: MyComplexAnimation(),
)

2. 列表优化

// 使用 ListView.builder 进行懒加载
ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text(items[index]),
    );
  },
)

测试

1. Widget 测试

testWidgets('Counter increments smoke test', (WidgetTester tester) async {
  await tester.pumpWidget(MyApp());
  expect(find.text('0'), findsOneWidget);
  expect(find.text('1'), findsNothing);

  await tester.tap(find.byIcon(Icons.add));
  await tester.pump();

  expect(find.text('0'), findsNothing);
  expect(find.text('1'), findsOneWidget);
});

2. 集成测试

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  testWidgets('tap on the floating action button, verify counter',
      (WidgetTester tester) async {
    app.main();
    await tester.pumpAndSettle();

    expect(find.text('0'), findsOneWidget);

    final Finder fab = find.byTooltip('Increment');
    await tester.tap(fab);
    await tester.pumpAndSettle();

    expect(find.text('1'), findsOneWidget);
  });
}

总结

通过本章节,我们深入探讨了 Flutter 的高级特性:

  1. 状态管理进阶

    • Provider 的使用
    • GetX 的实现
  2. 动画效果

    • 基础动画
    • 隐式动画
  3. 自定义 Widget

    • 自定义画布
    • 自定义手势
  4. 平台集成

    • 平台特定代码
    • 平台通道使用
  5. 性能优化

    • 构建优化
    • 列表优化
  6. 测试

    • Widget 测试
    • 集成测试

这些高级特性的掌握将帮助你构建更加复杂和高性能的 Flutter 应用。建议在实际项目中多加练习和运用这些概念,以加深理解和提高开发技能。