使用 Provider 管理 Flutter 应用状态 (上)
前言
一个应用内通常会有两种数据,部件内部的使用的临时性数据以及很多部件使用的全局性数据,部件内部使用的数据可以通过 StatefulWidget 来管理,但是全局性的数据如果通过从上到下传递的方式会使代码写的十分繁琐,这时就需要一个状态管理工具来进行管理了,本文说明如何使用 Provider 来管理这种应用的全局性的数据
什么是 Provider
官方的定义是: A mixture between dependency injection (DI) and state management, built with widgets for widgets. 翻译过来大意是一种依赖注入和状态管理的混合方案,使用部件创建,作用于部件 😅
为什么要使用 Provider
应用中通常会有一些很多部件都需要的数据,如用户的登录信息,用户设置,地理位置等,如果只是使用 StatefullWeight 的话就需要将状态提升到一个父部件中然后向下进行传递,会很繁琐,使用 provider 的话可以将对一种状态数据的操作放到一个文件内,然后使用到这个数据的部件只需要使用就可以了,当数据有变化时,部件会自动的重新构建,使界面更新。
一个例子 🌰
使用一个 todo 应用来说明如何在 Flutter 应用中使用 Provider,最终的完成的应用是这样的,可以新增,编辑和删除 todo。
创建应用
首先使用命令行创建一个项目
1 | flutter create flutter_provider_todos |
然后在项目的 pubspec.yml 添加 provider
1 | dependencies: |
创建一个 store 文件夹以及 todos.dart 用来存放应用中需要用到的全局性数据,新建一个 widget 目录,用来存放应用中的部件以及一个显示 todo 的页面 todos_page.dart
首先创建 todos 这个全局性的数据,修改 store/todos.dart,创建一个 Todo 类表示一个代办事项,然后实现 Todos 类, Todos 混合了 ChangeNotifier 类,为了使用 notifyListeners 方法来通知 UI 更新,因此需要导入 foundation.dart,Todos 类使用一个 _items 数组存放 Todo 数据,以及其它对 Todo 进行操作的方法。
1 | import 'package:flutter/foundation.dart'; |
然后使用 provider 提供的 ChangeNotifierProvider 方法将数据注册到整个应用,如果有多个数据就需要使用 MultiProvider 方法
1 | import 'package:flutter/material.dart'; |
列表页面
接着就是实现显示 todo 列表的页面,这个页面就是要用到 Todos 类里面的数据的部件,要使用 provider 的数据首先要导入 provider 以及对应的数据类 Todos,然后用 Consumer 加类型 Todos 来使用这个数据
1 | Consumer<Todos>( |
这个页面使用了一个 ListView.builder() 来渲染 Todos,然后每一项使用一个 ListTile 展示。新增,编辑和删除对应了 3 个不同的部件,分别是 AddTodoButton(),EditTodoButton(), RemoveTodoButton()
1 | // todos_page.dart |
实现功能
接下来就是要实现这 3 个按钮了,在 widget 目录创建对应的文件,每个按钮都会使用到 Todos 类里面定义的方法,所以都需要导入 provider 和 Todos 类,点击按钮会弹出一个对话框询问对应的操作,
添加 Todo 按钮
1 | import 'package:flutter/material.dart'; |
编辑 Todo 按钮
1 | import 'package:flutter/material.dart'; |
删除 Todo 按钮
1 | import 'package:flutter/material.dart'; |
可以看到要使用对应的方法需要的只是向对应的部件注入这个数据,然后使用就可以了
结语
使用了 provider 后,数据以及对一个 Todo 的操作都放在一个文件里面了,不用在多个层级间传递数据,并且在数据变化时自动更新了 UI,所以是十分有必要的。