前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >使用Provider来进行状态管理

使用Provider来进行状态管理

作者头像
拉维
发布2019-10-14 16:29:11
发布2019-10-14 16:29:11
2.2K00
代码可运行
举报
文章被收录于专栏:iOS小生活iOS小生活
运行总次数:0
代码可运行

当我们想在多个页面(组件/Widget)之间共享状态(数据),或者一个页面(组件/WIdget)的多个子组件之间共享状态(数据),这个时候我们就需要用Flutter中的状态管理来管理统一的状态(数据),实现不同组件间直接的传值和数据共享。

今天我们来介绍一下Flutter官方提供的状态管理解决方案——Provider。

首先,我们在pub.dev里面搜provider,然后按照文档在Fluter项目中配置依赖

第二步,在lib目录下新增一个provider文件夹,然后在该文件夹内放我们的各个状态管理类。(本例中我们新建了一个Counter.dart)

第三步,实现上一步定义的状态管理类

代码语言:javascript
代码运行次数:0
运行
复制
//Counter
import 'package:flutter/material.dart';

class Counter with ChangeNotifier {

  int _count = 0;//在不同组件之间共享的状态

  /**
   * 定义一个get方法,在外界获取私有状态值
   */
  int get count => _count;
  
  //增加数量(更新状态)
  incCount(){
    print(_count);
    this._count++;
    //表示更新状态.它会重新触发所有监听了该Provider的类的build方法
    //在本例中,当notifyListeners方法执行的时候,购物车页面与我的页面的build方法都会被重新触发
    notifyListeners();
  }
  
}

第四步,在main.dart里面配置全局监听

代码语言:javascript
代码运行次数:0
运行
复制
//main.dart
import 'package:flutter_jdshop/provider/Counter.dart';
import 'package:provider/provider.dart';

void main() => runApp(MyApp());

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      //在MaterialApp外层嵌套一个MultiProvider
      providers: [
        /** 在这里面配置全局监听的类*/
        ChangeNotifierProvider(builder: (_) => Counter()),
      ],
      child: MaterialApp(
        initialRoute: "/", //初始路由
        onGenerateRoute: prefix0.onGenerateRoute, //配置路由
        theme: ThemeData(
          primaryColor: Colors.white, //导航栏背景颜色
        ),
        debugShowCheckedModeBanner: false, //取出右上角DEBUG
      ),
    );
  }
}

第五步,在对应的页面实现状态的获取与更新。如下是我分别在“购物车”页面和“我的”页面里面进行数量更新与获取的演示。

“购物车”页面更新数据:

代码语言:javascript
代码运行次数:0
运行
复制
import 'dart:developer';
import 'package:flutter_jdshop/provider/Counter.dart';
import 'package:flutter/material.dart';
import 'package:flutter_jdshop/services/ScreenAdaptation.dart';
import 'package:provider/provider.dart';

class ShoppingCartPage extends StatefulWidget {
  ShoppingCartPage({Key key}) : super(key: key);

  _ShoppingCartPageState createState() => _ShoppingCartPageState();
}

class _ShoppingCartPageState extends State<ShoppingCartPage> {

  @override
  Widget build(BuildContext context) {
    ScreenAdaptation.init(context);
    //获取Provider对象
    var counterProvider = Provider.of<Counter>(context);
    return Scaffold(
      appBar: _buildAppBarWidget(),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          //更新状态
          counterProvider.incCount();
        },
      ),
      body: Center(
        //获取Provider的状态值
        child: Text("购物车页面:${counterProvider.count}",
            style: TextStyle(fontSize: 20)),
      ),
    );
  }
}

“我的”页面获取数据:

代码语言:javascript
代码运行次数:0
运行
复制
import 'package:flutter/material.dart';
import 'package:flutter_jdshop/provider/Counter.dart';
import 'package:provider/provider.dart';

class UserPage extends StatefulWidget {
  UserPage({Key key}) : super(key: key);

  _UserPageState createState() => _UserPageState();
}

class _UserPageState extends State<UserPage> {
  @override
  Widget build(BuildContext context) {
    //获取Provider对象
    var counterProvider = Provider.of<Counter>(context);
    return Scaffold(
      appBar: AppBar(
        title: Text("用户页面"),
      ),
      body: Center(
          //获取Provider的状态值
          child: Text("用户页面,${counterProvider.count}",
              style: TextStyle(fontSize: 20))),
    );
  }
}

到此为止,使用Provider进行状态管理的步骤就说完了,上面代码的演示效果如下:

上面我介绍了使用Provider进行状态管理的步骤,以及演示了一个实例。接下来我们考虑一个问题。

上例中的状态管理类Counter中的状态值_count,初始化该值的时候,如果该初始值不需要计算,我们在声明_count的时候进行初始赋值即可,如下:

代码语言:javascript
代码运行次数:0
运行
复制
class Counter with ChangeNotifier {

  //在这里进行初始赋值
  int _count = 0;//在不同组件之间共享的状态

  /**
   * 定义一个get方法,在外界获取私有状态值
   */
  int get count => _count;
  
  //增加数量(更新状态)
  incCount(){
    print(_count);
    this._count++;
    notifyListeners();//表示更新状态
  }
  
}

但是如果该初始值需要计算得到,那么我们可以在Counter的构造函数中进行该计算。因为我们需要在main.dart中配置全局监听的类(这里是Counter类),配置的时候需要实例化该类(Counter),也就是会触发Counter的构造函数

实例

第1步,定义一个状态管理类Cart:

代码语言:javascript
代码运行次数:0
运行
复制
import 'package:flutter/material.dart';

class Cart with ChangeNotifier {
  
  List _productList = [];

  List get productList => this._productList;
  int get productNum => this.productList.length;

  //增加商品
  addProduct(productName){
    this.productList.add(productName);
    notifyListeners();
  }

  //删除商品
  deleteProduct(){
    this.productList.removeLast();
    notifyListeners();
  }
}

第2步,在main.dart里面配置全局监听:

代码语言:javascript
代码运行次数:0
运行
复制
void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  MyApp({Key key}) : super(key: key);

  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      //在MaterialApp外层嵌套一个MultiProvider
      providers: [
        /** 在这里面配置全局监听的类*/
        ChangeNotifierProvider(builder: (_) => Counter()),
        ChangeNotifierProvider(builder: (_) => Cart()),
      ],
      child: MaterialApp(
        initialRoute: "/", //初始路由
        onGenerateRoute: prefix0.onGenerateRoute, //配置路由
        theme: ThemeData(
          primaryColor: Colors.white, //导航栏背景颜色
        ),
        debugShowCheckedModeBanner: false, //取出右上角DEBUG
      ),
    );
  }
}

第3步,在对应的页面实现状态的获取与更新。

在购物车页面更新与获取状态:

代码语言:javascript
代码运行次数:0
运行
复制
@override
  Widget build(BuildContext context) {
    ScreenAdaptation.init(context);
    //获取Provider对象(Cart)
    var cartProvider = Provider.of<Cart>(context);
    return Scaffold(
      appBar: _buildAppBarWidget(),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          //更新状态(给购物车列表增加数据)
          cartProvider.addProduct("山核桃");
        },
      ),
      body: ListView(
        children: <Widget>[
          CartPage(),
          Divider(height: 5),
          //获取Provider的状态值(购物车中商品数量)
          Text("数量:${cartProvider.productNum}"),
        ],
      ),
    );
  }

在封装的购物车商品展示组件CartPage中获取provider状态:

代码语言:javascript
代码运行次数:0
运行
复制
import 'package:flutter/material.dart';
import 'package:flutter_jdshop/provider/Cart.dart';
import 'package:provider/provider.dart';

class CartPage extends StatefulWidget {
  CartPage({Key key}) : super(key: key);

  _CartPageState createState() => _CartPageState();
}

class _CartPageState extends State<CartPage> {
  @override
  Widget build(BuildContext context) {
    //获取Provider对象
    var cartProvider = Provider.of<Cart>(context);

    return Column(
      //获取Provider的状态值(购物车中的商品)
      children: cartProvider.productList.map((value) {
        return ListTile(
          title: Text(value),
          trailing: IconButton(
            icon: Icon(Icons.delete),
            onPressed: (){
              //修改Provider的状态值(删除)
              cartProvider.deleteProduct();
            },
          ),
        );
      }).toList(),
    );
  }
}

以上的效果如下:

以上。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-10-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 iOS小生活 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档