Flutter: 使用 Provider 管理状态

状态也可以说是数据,某个组件的数据其他组件可以直接访问,不管中间间隔多少层。

这一功能相当于 Vue 的 Vuex,React 的 Redux 或者 useContext 钩子函数,Flutter 使用 Provider 实现状态管理。

用法简要步骤:

1. pubspec.yaml 增加 provider 行:

dependencies:
  flutter:
    sdk: flutter
  provider: ^4.0.0  // 最新的版本其实是 6.0.3

保存文件就行,flutter 会自动下载 provider package

2. 设置需要共享的状态/数据

简单地说,就是使用 mixin,例如在类后面加 with ChangeNotifier, 例如:

// products.dart
import 'package:flutter/material.dart';
import './product.dart';

class Products with ChangeNotifier {
  List<Product> _items = [
    Product(
      id: 'p1',
      title: 'Red Shirt',
      description: 'A red shirt - it is pretty red!',
      price: 29.99,
      imageUrl:
          'https://cdn.pixabay.com/photo/2017/07/10/17/49/man-2490785_960_720.jpg',
    ),
  ];

  // getter
  List<Product> get items {  
    return [..._items];
  }

  Product findById(String id) {
    return _items.firstWhere((prod) => prod.id == id);
  }

  void addProduct() {
    // _items.add(item);
    notifyListeners();
  }
}

3. 在上层组件里加 ChangeNotifierProvider

例如 main.dart:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import './screens/products_overview_screen.dart';
import './screens/product_detail_screen.dart';
import './providers/products.dart';

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
    	
      //  如果 provider 3.0.0, 此处用 builder 属性,
      // 但是会出现奇怪的异常,因此使用较高版本,使用 create 属性
      create: (_) => Products(),  
      child: MaterialApp(
          title: 'MyShop',
          theme: ThemeData(
            primarySwatch: Colors.purple,
            accentColor: Colors.purple.shade50,
            fontFamily: 'Lato',
          ),
          home: ProductsOverviewScreen(),
          routes: {
            ProductDetailScreen.routeName: (ctx) => ProductDetailScreen(),
          }),
    );
  }
}

4. 底层组件使用 Provider.of<Products>(context) 获得数据

例如:

// products_grid.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import './product_item.dart';
import '../providers/products.dart';

class ProductsGrid extends StatelessWidget {
  
  Widget build(BuildContext context) {
    final productsData = Provider.of<Products>(context);
    final products = productsData.items;  // 获得全部 products
    return GridView.builder(
      padding: EdgeInsets.all(10),
      itemCount: products.length,
      itemBuilder: (ctx, i) => ChangeNotifierProvider(
        create: (c) => products[i],
        child: ProductItem(),
      ),
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
        childAspectRatio: 3 / 2,
        crossAxisSpacing: 10,
        mainAxisSpacing: 10,
      ),
    );
  }
}

provider 可以嵌套

例如上述代码:

itemBuilder: (ctx, i) => ChangeNotifierProvider(
        create: (c) => products[i],
        child: ProductItem(),
      ),

因此product_item.dart 里可以直接获得对应的单个 product,否则需要使用构造函数传递数据:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../screens/product_detail_screen.dart';
import '../providers/product.dart';

class ProductItem extends StatelessWidget {

  
  Widget build(BuildContext context) {
    final product = Provider.of<Product>(context);  // 通过 provider 获取 product
    return ClipRRect(
      borderRadius: BorderRadius.circular(10),
      child: GridTile(
        child: GestureDetector(
          onTap: () {
            Navigator.of(context).pushNamed(
              ProductDetailScreen.routeName,
              arguments: product.id,
            );
          },
          child: Image.network(
            product.imageUrl,
            fit: BoxFit.cover,
          ),
        ),
        footer: GridTileBar(
          backgroundColor: Colors.black54,
          leading: IconButton(
            icon: Icon(
                product.isFavorite ? Icons.favorite : Icons.favorite_border),
            color: Theme.of(context).accentColor,
            onPressed: () {
              product.toggleFavoriteStatus();
            },
          ),
          title: Text(
            product.title,
            textAlign: TextAlign.center,
          ),
          trailing: IconButton(
            icon: Icon(Icons.shopping_cart),
            color: Theme.of(context).accentColor,
            onPressed: () {},
          ),
        ),
      ),
    );
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Flutter状态管理Provider是一种用于管理Flutter应用程序状态的库。它提供了一种简单的方式来管理应用程序的状态,使得开发者可以更加轻松地构建复杂的应用程序。使用Provider,开发者可以轻松地将状态从一个小部件传递到另一个小部件,而无需手动管理状态。这使得代码更加简洁,易于维护。同时,Provider还提供了一些高级功能,如异步状态管理和依赖注入。总之,Provider是一个非常有用的Flutter状态管理库,可以帮助开发者更加轻松地构建高质量的应用程序。 ### 回答2: Flutter 是一种最快速开发应用程序的框架之一。Flutter 中有很多不同的状态管理工具,其中最受欢迎的是 ProviderProvider 是一个包含了多个 Flutter 应用程序的不同状态或数据的管理工具。Provider 使您可以轻松访问和管理应用程序的各个部分中的数据。 Provider 有两个基本要素:一个是 Provider,另一个是 Consumer。Provider 可以包含任何数据,例如字符串、整数、对象、函数等等。而 Consumer 是能够访问这些数据并显示它们的 Widget。 Provider 可以在整个应用程序中共享数据和状态。如果您需要在应用程序的多个部分中保持数据的同步状态,则可以使用 Provider管理这些数据和状态。在使用 Provider 之前,您需要定义一个类并将其继承自 ChangeNotifier。该类将包含数据和状态,并且还需要通过 notifyListeners() 告知侦听数据的 Consumer。 使用 Provider 的好处是封装了状态管理的代码。这样,您不必在应用程序或 Widget 中编写大量的状态管理代码。在使用 Provider 之后,您可以轻松地在应用程序或 Widget 中访问数据和状态。 最后,值得一提的是,Provider使用方式很多,您可以使用官方提供的 Provider 包来管理应用程序中的数据和状态,也可以使用其他第三方状态管理工具来实现您的应用程序的功能。在使用任何工具之前,请确保仔细了解它们的优缺点,以便于选择最适合您的应用程序的状态管理工具。 ### 回答3: Flutter是一个非常强大的UI框架,但随着应用规模增大,状态管理变得越来越复杂,导致代码可读性和可维护性变得很难。Flutter状态管理解决方案有多种,其中比较常用的就是ProviderProviderFlutter中一个状态管理框架,它使用InheritedWidget来传递状态,同时具有透明性、灵活性和便捷性。通过Provider,我们可以在不同Widget之间共享相同的数据,从而保证数据在应用中的一致性。 使用Provider的步骤非常简单,首先需要在我们的Flutter项目中引入Flutter Provider库,然后定义我们需要共享的数据模型,并将其包装在Provider中,最后在UI界面中使用数据。 下面是一篇使用Provider实现商品购物车的例子: 1.定义数据模型 ``` class Product { String title; double price; Product({ required this.title, required this.price, }); } ``` 2.创建Provider ``` class CartModel extends ChangeNotifier { final List<Product> _items = []; List<Product> get items => _items; void add(Product product) { _items.add(product); notifyListeners(); } void remove(Product product) { _items.remove(product); notifyListeners(); } } ``` 3.在Widget树中使用Provider ``` return ChangeNotifierProvider( create: (context) => CartModel(), child: MaterialApp( home: Scaffold( body: Center( child: Consumer<CartModel>( builder: (context, cart, child) { return Text('Cart items: ${cart.items.length}'); }, ), ), ), ), ); ``` 在上面的代码中,我们使用ChangeNotifierProvider包装了CartModel,并将其注册到应用的根节点。Consumer在UI界面中使用CartModel的数据,并提供数据发生变化时的回调闭包。 总的来说,Provider能够在Flutter应用中实现更清晰、安全和高效的状态管理,在开发中能够带来更好的用户体验和开发效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值