Mobile Development7 min read

Flutter Advanced Patterns

Advanced Flutter: Riverpod state management, custom painters, platform channels, performance optimization, and modular app architecture.

flutterdartmobilestate-management

Flutter enables cross-platform apps for iOS, Android, web, and desktop from a single Dart codebase. Advanced Flutter goes beyond basic widgets to cover state management architecture, custom rendering, native platform integration, and performance optimization.

Use Riverpod 2.0 for state management (code generation + AsyncNotifier). Use Go Router for navigation. Build custom painters for bespoke UI. Use platform channels for native APIs not covered by Flutter plugins. Profile with DevTools before optimizing.

Workflow

  1. Structure state with Riverpod 2.0Riverpod's code-generated providers eliminate boilerplate and provide compile-time safety.
  2. Build custom UI with CustomPainterCustomPainter gives pixel-level control for charts, gauges, animations, and effects not achievable with standard widgets.
  3. Integrate native code with platform channelsPlatform channels call native Swift/Kotlin code for capabilities not covered by existing Flutter plugins.
  4. Implement navigation with Go RouterGo Router provides declarative, deep-link-aware navigation with type-safe routes.
  5. Profile and optimize Flutter performanceJank (dropped frames) in Flutter is caused by expensive builds, layouts, or paints - visible with DevTools.

Output Format

Riverpod 2.0 with code generation, Go Router navigation with deep links, CustomPainter for bespoke UI, platform channel for native feature, DevTools profile showing 60fps.

Examples

Riverpod notifier: `@riverpod class CartNotifier extends _$CartNotifier { @override List<Item> build() => []; void add(Item item) => state = [...state, item]; }`
CustomPainter: `class ProgressPainter extends CustomPainter { @override void paint(Canvas c, Size s) { c.drawArc(Rect.fromCircle(center: s.center, radius: 40), -pi/2, 2*pi*progress, false, Paint()..style = PaintingStyle.stroke..strokeWidth = 8..color = Colors.blue); } @override bool shouldRepaint(covariant ProgressPainter old) => old.progress != progress; }`
Platform channel: `final level = await const MethodChannel("battery").invokeMethod<int>("getBatteryLevel"); setState(() => _battery = level ?? 0)`

Edge Cases & Gotchas

  • Riverpod ref.invalidate vs ref.refresh: invalidate disposes the provider for next read; refresh disposes AND reads immediately - use invalidate for lazy re-computation
  • Platform channel on background isolates: method channels must be called from the main isolate; use `IsolateNameServer` or `compute()` for heavy processing then channel on main thread
  • Web target: some Flutter features (platform channels, some plugins) don't work on web; check `kIsWeb` and provide web alternatives for cross-platform apps

When to Break These Rules

  • For apps with complex platform-specific UI per platform (completely different iOS and Android designs), consider native development - Flutter's UI homogeneity is a trade-off.

Reference Files

  • Riverpod docs: https://riverpod.dev/
  • Go Router: https://pub.dev/packages/go_router
  • Flutter DevTools: https://docs.flutter.dev/tools/devtools
  • Platform channels: https://docs.flutter.dev/platform-integration/platform-channels

More skills in this library

Browse all technical skills - Mobile, AI/ML, Web, Backend, Design, and Product.