在这里插入图片描述

案例概述

Provider 是 Flutter 中最流行的状态管理库。它提供了简洁的 API 来管理应用状态,避免了复杂的 setState 调用。Provider 支持多种提供者类型,如 Provider、ChangeNotifier、StreamProvider 等。本案例展示了如何使用 Provider 进行状态管理。

核心概念

1. Provider 基础

Provider 是一个 InheritedWidget 的包装,用于在 Widget 树中共享数据。通过 Provider.of() 或 Consumer 可以访问提供的数据。Provider 支持自动依赖注入和生命周期管理。

2. ChangeNotifier

ChangeNotifier 是一个可观察的对象,当数据变化时会通知所有监听者。通过继承 ChangeNotifier 并调用 notifyListeners(),可以实现响应式的状态管理。

3. 多个提供者

可以使用 MultiProvider 组合多个提供者,创建复杂的状态管理结构。

代码详解

示例 1:基础计数器

class CounterModel extends ChangeNotifier {
  int _count = 0;

  int get count => _count;

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

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

class BasicCounterExample extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => CounterModel(),
      child: Scaffold(
        appBar: AppBar(title: const Text('基础计数器')),
        body: Center(
          child: Consumer<CounterModel>(
            builder: (context, counter, child) {
              return Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text('计数: ${counter.count}'),
                  ElevatedButton(
                    onPressed: () => counter.increment(),
                    child: const Text('增加'),
                  ),
                ],
              );
            },
          ),
        ),
      ),
    );
  }
}

代码解释: 这个示例展示了 Provider 的基础用法。首先创建一个继承 ChangeNotifier 的模型类,定义状态和修改状态的方法。然后使用 ChangeNotifierProvider 提供这个模型,使用 Consumer 访问模型数据。当调用 notifyListeners() 时,Consumer 会自动重建。

示例 2:字符串状态管理

class TextModel extends ChangeNotifier {
  String _text = '';

  String get text => _text;

  void updateText(String newText) {
    _text = newText;
    notifyListeners();
  }

  void clear() {
    _text = '';
    notifyListeners();
  }
}

class TextStateExample extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => TextModel(),
      child: Scaffold(
        appBar: AppBar(title: const Text('文本状态管理')),
        body: Padding(
          padding: const EdgeInsets.all(16),
          child: Column(
            children: [
              TextField(
                onChanged: (value) {
                  context.read<TextModel>().updateText(value);
                },
                decoration: const InputDecoration(
                  hintText: '输入文本',
                  border: OutlineInputBorder(),
                ),
              ),
              const SizedBox(height: 16),
              Consumer<TextModel>(
                builder: (context, textModel, child) {
                  return Text('输入的文本: ${textModel.text}');
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}

代码解释: 这个示例展示了如何管理字符串状态。通过 context.read() 可以获取模型实例并调用方法。Consumer 用于监听状态变化并重建 UI。

示例 3:列表状态管理

class ListModel extends ChangeNotifier {
  List<String> _items = [];

  List<String> get items => _items;

  void addItem(String item) {
    _items.add(item);
    notifyListeners();
  }

  void removeItem(int index) {
    _items.removeAt(index);
    notifyListeners();
  }
}

class ListStateExample extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => ListModel(),
      child: Scaffold(
        appBar: AppBar(title: const Text('列表状态管理')),
        body: Consumer<ListModel>(
          builder: (context, listModel, child) {
            return ListView.builder(
              itemCount: listModel.items.length,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text(listModel.items[index]),
                  trailing: IconButton(
                    icon: const Icon(Icons.delete),
                    onPressed: () => listModel.removeItem(index),
                  ),
                );
              },
            );
          },
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            context.read<ListModel>().addItem('新项目');
          },
          child: const Icon(Icons.add),
        ),
      ),
    );
  }
}

代码解释: 这个示例展示了如何管理列表状态。通过 addItem() 和 removeItem() 方法修改列表,每次修改都会调用 notifyListeners() 通知所有监听者。

示例 4:多个状态管理

class MultiStateExample extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context) => CounterModel()),
        ChangeNotifierProvider(create: (context) => TextModel()),
      ],
      child: Scaffold(
        appBar: AppBar(title: const Text('多个状态管理')),
        body: Column(
          children: [
            Consumer<CounterModel>(
              builder: (context, counter, child) {
                return Text('计数: ${counter.count}');
              },
            ),
            Consumer<TextModel>(
              builder: (context, textModel, child) {
                return Text('文本: ${textModel.text}');
              },
            ),
          ],
        ),
      ),
    );
  }
}

代码解释: 这个示例展示了如何使用 MultiProvider 管理多个状态。通过 MultiProvider 可以提供多个不同类型的模型,每个 Consumer 可以访问特定的模型。

示例 5:状态重置

class ResetableModel extends ChangeNotifier {
  int _count = 0;
  final int _initialCount = 0;

  int get count => _count;

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

  void reset() {
    _count = _initialCount;
    notifyListeners();
  }
}

class ResetStateExample extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => ResetableModel(),
      child: Scaffold(
        appBar: AppBar(title: const Text('状态重置')),
        body: Center(
          child: Consumer<ResetableModel>(
            builder: (context, model, child) {
              return Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text('计数: ${model.count}'),
                  ElevatedButton(
                    onPressed: () => model.increment(),
                    child: const Text('增加'),
                  ),
                  ElevatedButton(
                    onPressed: () => model.reset(),
                    child: const Text('重置'),
                  ),
                ],
              );
            },
          ),
        ),
      ),
    );
  }
}

代码解释: 这个示例展示了如何实现状态重置功能。通过 reset() 方法将状态恢复到初始值。这种方式适合需要重置表单、清空缓存等场景。

高级话题

1. 动态/响应式设计

Provider 可以根据屏幕大小提供不同的状态。

2. 动画与过渡

状态变化可以驱动动画。

3. 搜索/过滤/排序

状态可以包含搜索、过滤、排序的结果。

4. 选择与批量操作

支持选择和批量操作列表项。

5. 加载与缓存

状态可以缓存已加载的数据。

6. 键盘导航

支持键盘快捷键修改状态。

7. 无障碍支持

通过 Semantics 提供无障碍支持。

8. 样式自定义

根据状态动态改变样式。

9. 数据持久化/导出

状态可以保存到本地存储。

10. 单元测试与集成测试

状态管理逻辑可以通过单元测试验证。

PC 端适配要点

  • 根据屏幕宽度调整 UI 布局
  • 支持键盘快捷键
  • 提供清晰的状态指示

实际应用场景

  • 用户认证:管理登录状态
  • 购物车:管理商品列表
  • 主题切换:管理应用主题
  • 语言切换:管理应用语言

扩展建议

  • 学习 Riverpod 等其他状态管理库
  • 研究复杂的状态管理模式
  • 探索与其他库的集成
  • 学习性能优化技巧

总结

Provider 是 Flutter 中强大的状态管理库。通过正确使用 Provider,可以创建可维护和可扩展的应用。理解 ChangeNotifier、Provider、Consumer 等核心概念是关键。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐