跳转至

第12章 Flutter状态管理与路由

Flutter状态管理与路由图

学习目标:掌握Flutter状态管理方案(Provider、Riverpod、Bloc)和导航路由系统。

预计学习时间:7-10天 实践时间:3-4天


目录

  1. 状态管理概述
  2. Provider状态管理
  3. Riverpod状态管理
  4. Bloc状态管理
  5. 导航与路由
  6. 实践练习

1. 状态管理概述

1.1 状态管理方案对比

方案 复杂度 适用场景 学习曲线
setState 简单页面 平缓
Provider 中小型应用 平缓
Riverpod 中大型应用 中等
Bloc 大型复杂应用 陡峭
GetX 快速开发 平缓

1.2 选择建议

  • 新手:从Provider开始
  • 中大型项目:Riverpod或Bloc
  • 快速原型:GetX

2. Provider状态管理

2.1 基础使用

Dart
// 添加依赖
// pubspec.yaml
dependencies:
  provider: ^6.1.1

// 定义Model
class CounterModel extends ChangeNotifier {
  int _count = 0;

  int get count => _count;

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

  void decrement() {
    _count--;
    notifyListeners();
  }
}

// 提供Model
void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => CounterModel(),
      child: MyApp(),
    ),
  );
}

// 使用Model
class CounterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Consumer<CounterModel>(
          builder: (context, counter, child) {
            return Text('Count: ${counter.count}');
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          context.read<CounterModel>().increment();
        },
        child: Icon(Icons.add),
      ),
    );
  }
}

2.2 多Provider管理

Dart
// MultiProvider管理多个状态
void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => UserModel()),
        ChangeNotifierProvider(create: (_) => CartModel()),
        ChangeNotifierProvider(create: (_) => ThemeModel()),
      ],
      child: MyApp(),
    ),
  );
}

3. Riverpod状态管理

3.1 基础使用

Dart
// 添加依赖
dependencies:
  flutter_riverpod: ^2.4.9

// 定义Provider
final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) {
  return CounterNotifier();
});

class CounterNotifier extends StateNotifier<int> {
  CounterNotifier() : super(0);

  void increment() => state++;
  void decrement() => state--;
}

// 使用Provider
class CounterPage extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(counterProvider);

    return Scaffold(
      body: Center(child: Text('Count: $count')),
      floatingActionButton: FloatingActionButton(
        onPressed: () => ref.read(counterProvider.notifier).increment(),
        child: Icon(Icons.add),
      ),
    );
  }
}

4. Bloc状态管理

4.1 基础架构

Dart
// Event
counter_event.dart
abstract class CounterEvent {}
class CounterIncrementPressed extends CounterEvent {}
class CounterDecrementPressed extends CounterEvent {}

// State
counter_state.dart
class CounterState {
  final int count;
  CounterState({required this.count});
}

// Bloc
counter_bloc.dart
class CounterBloc extends Bloc<CounterEvent, CounterState> {
  CounterBloc() : super(CounterState(count: 0)) {
    on<CounterIncrementPressed>((event, emit) {
      emit(CounterState(count: state.count + 1));
    });
    on<CounterDecrementPressed>((event, emit) {
      emit(CounterState(count: state.count - 1));
    });
  }
}

5. 导航与路由

5.1 基础导航

Dart
// 页面跳转
Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => DetailPage()),
);

// 返回
Navigator.pop(context);

// 替换页面
Navigator.pushReplacement(
  context,
  MaterialPageRoute(builder: (context) => HomePage()),
);

5.2 命名路由

Dart
// 定义路由
MaterialApp(
  routes: {
    '/': (context) => HomePage(),
    '/detail': (context) => DetailPage(),
    '/settings': (context) => SettingsPage(),
  },
);

// 跳转
Navigator.pushNamed(context, '/detail');

5.3 GoRouter(推荐)

Dart
// 添加依赖
dependencies:
  go_router: ^12.1.1

// 配置路由
final _router = GoRouter(
  routes: [
    GoRoute(
      path: '/',
      builder: (context, state) => HomePage(),
    ),
    GoRoute(
      path: '/detail/:id',
      builder: (context, state) {
        final id = state.pathParameters['id'];
        return DetailPage(id: id);
      },
    ),
  ],
);

// 使用
MaterialApp.router(
  routerConfig: _router,
);

// 导航
context.go('/detail/123');
context.push('/detail/123');

6. 实践练习

练习1:购物车状态管理

任务:使用Provider实现购物车功能

要求: - 商品列表 - 添加/删除商品 - 计算总价 - 跨页面状态共享

练习2:新闻应用路由

任务:使用GoRouter实现新闻应用导航

要求: - 首页列表 - 详情页(带参数) - 深层链接支持 - 路由守卫


本章小结

核心要点

  1. Provider适合中小型应用,学习曲线平缓
  2. Riverpod是Provider的升级版,更安全易用
  3. Bloc适合大型复杂应用,逻辑清晰可预测
  4. GoRouter是Flutter推荐的声明式路由方案

下一步

完成本章学习后,请进入第13章:Flutter与原生交互


本章完成时间:预计7-10天