Skip to content

Flutter 状态管理

状态管理方案对比

方案复杂度适用场景
setState组件内简单状态
InheritedWidget跨组件数据传递
Provider中小型应用
Riverpod中高类型安全、可测试
Bloc大型应用、复杂业务

Provider

基础使用

dart
import 'package:provider/provider.dart';

// 1. 定义状态
class Counter with ChangeNotifier {
  int _count = 0;
  int get count => _count;
  
  void increment() {
    _count++;
    notifyListeners();
  }
}

// 2. 提供状态
void main() {
  runApp(
    ChangeNotifierProvider(
      create: (_) => Counter(),
      child: MyApp(),
    ),
  );
}

// 3. 消费状态
class CounterWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 监听变化
    final counter = context.watch<Counter>();
    
    return Column(
      children: [
        Text('Count: ${counter.count}'),
        ElevatedButton(
          // 只读取,不监听
          onPressed: () => context.read<Counter>().increment(),
          child: Text('Increment'),
        ),
      ],
    );
  }
}

多 Provider

dart
MultiProvider(
  providers: [
    ChangeNotifierProvider(create: (_) => UserModel()),
    ChangeNotifierProvider(create: (_) => CartModel()),
    Provider(create: (_) => ApiService()),
  ],
  child: MyApp(),
)

Riverpod

基础使用

dart
import 'package:flutter_riverpod/flutter_riverpod.dart';

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

class CounterNotifier extends StateNotifier<int> {
  CounterNotifier() : super(0);
  
  void increment() => state++;
  void decrement() => state--;
}

// 2. 使用 ProviderScope
void main() {
  runApp(
    ProviderScope(child: MyApp()),
  );
}

// 3. 消费状态
class CounterWidget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(counterProvider);
    
    return Column(
      children: [
        Text('Count: $count'),
        ElevatedButton(
          onPressed: () => ref.read(counterProvider.notifier).increment(),
          child: Text('Increment'),
        ),
      ],
    );
  }
}

异步 Provider

dart
final userProvider = FutureProvider<User>((ref) async {
  final response = await http.get('https://api.example.com/user');
  return User.fromJson(jsonDecode(response.body));
});

class UserWidget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final userAsync = ref.watch(userProvider);
    
    return userAsync.when(
      loading: () => CircularProgressIndicator(),
      error: (err, stack) => Text('Error: $err'),
      data: (user) => Text('Hello, ${user.name}'),
    );
  }
}

Bloc

基础使用

dart
import 'package:flutter_bloc/flutter_bloc.dart';

// 1. 定义 Event
abstract class CounterEvent {}
class IncrementEvent extends CounterEvent {}
class DecrementEvent extends CounterEvent {}

// 2. 定义 State
class CounterState {
  final int count;
  CounterState(this.count);
}

// 3. 定义 Bloc
class CounterBloc extends Bloc<CounterEvent, CounterState> {
  CounterBloc() : super(CounterState(0)) {
    on<IncrementEvent>((event, emit) {
      emit(CounterState(state.count + 1));
    });
    
    on<DecrementEvent>((event, emit) {
      emit(CounterState(state.count - 1));
    });
  }
}

// 4. 提供 Bloc
BlocProvider(
  create: (_) => CounterBloc(),
  child: CounterWidget(),
)

// 5. 消费 Bloc
class CounterWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocBuilder<CounterBloc, CounterState>(
      builder: (context, state) {
        return Column(
          children: [
            Text('Count: ${state.count}'),
            ElevatedButton(
              onPressed: () => context.read<CounterBloc>().add(IncrementEvent()),
              child: Text('Increment'),
            ),
          ],
        );
      },
    );
  }
}

Cubit(简化版 Bloc)

dart
class CounterCubit extends Cubit<int> {
  CounterCubit() : super(0);
  
  void increment() => emit(state + 1);
  void decrement() => emit(state - 1);
}

// 使用
BlocBuilder<CounterCubit, int>(
  builder: (context, count) => Text('Count: $count'),
)

状态管理选择

简单应用                    复杂应用
    │                          │
    ▼                          ▼
setState ──▶ Provider ──▶ Riverpod ──▶ Bloc


                        GetX (争议较多)

面试要点

  1. Provider 原理:InheritedWidget + ChangeNotifier
  2. Riverpod 优势:编译时安全、无 BuildContext 依赖
  3. Bloc 模式:Event -> Bloc -> State 单向数据流
  4. 选型建议:根据团队经验和项目规模选择

前端面试知识库