插件介绍

Provider Shopper 是一个基于 Flutter 开发的购物应用示例,展示了如何使用 Provider 包进行高效的状态管理。这个应用不仅展示了基本的 Provider 用法,还包含了高级用法如 ProxyProviderMultiProvider 的实际应用。

核心功能与特性

  • 商品目录管理:展示可购买的商品列表,支持浏览和查看详细信息
  • 购物车功能:添加/删除商品,实时计算总价
  • 状态管理:使用 Provider 包实现高效的状态共享和更新
  • 路由导航:使用 GoRouter 实现页面之间的导航
  • 跨平台适配:支持鸿蒙平台及其他主流平台

技术架构

  • 状态管理:基于 Provider 包的 ChangeNotifierProxyProviderMultiProvider
  • 路由管理:使用 GoRouter 实现声明式路由
  • UI 组件:遵循 Material Design 规范,支持响应式布局
  • 平台适配:鸿蒙平台原生适配支持

使用步骤

1. 包的引入

由于这是一个自定义修改版本,需要通过 Git 形式引入。在你的 Flutter 项目的 pubspec.yaml 文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter

  # Provider Shopper 自定义包
  provider_shopper:
    git:
      url: "https://atomgit.com/"
      path: "packages/provider_shopper/provider_shopper"

  # 必要的依赖项
  provider: ^6.0.2
  go_router: ^10.0.0

然后运行 flutter pub get 安装依赖。

2. 基本配置

2.1 初始化 Provider

在应用入口文件 main.dart 中,使用 MultiProvider 配置应用所需的状态管理对象:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:provider_shopper/common/theme.dart';
import 'package:provider_shopper/models/cart.dart';
import 'package:provider_shopper/models/catalog.dart';
import 'package:provider_shopper/screens/cart.dart';
import 'package:provider_shopper/screens/catalog.dart';
import 'package:provider_shopper/screens/login.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    // Using MultiProvider is convenient when providing multiple objects.
    return MultiProvider(
      providers: [
        // In this sample app, CatalogModel never changes, so a simple Provider
        // is sufficient.
        Provider(create: (context) => CatalogModel()),
        // CartModel is implemented as a ChangeNotifier, which calls for the use
        // of ChangeNotifierProvider. Moreover, CartModel depends
        // on CatalogModel, so a ProxyProvider is needed.
        ChangeNotifierProxyProvider<CatalogModel, CartModel>(
          create: (context) => CartModel(),
          update: (context, catalog, cart) {
            if (cart == null) throw ArgumentError.notNull('cart');
            cart.catalog = catalog;
            return cart;
          },
        ),
      ],
      child: MaterialApp(
        title: 'Provider Demo',
        theme: appTheme,
        initialRoute: '/login',
        routes: {
          '/login': (context) => const MyLogin(),
          '/catalog': (context) => const MyCatalog(),
          '/cart': (context) => const MyCart(),
        },
      ),
    );
  }
}
2.2 配置路由

使用 GoRouter 实现声明式路由配置:

import 'package:go_router/go_router.dart';
import 'package:provider_shopper/screens/cart.dart';
import 'package:provider_shopper/screens/catalog.dart';
import 'package:provider_shopper/screens/login.dart';

GoRouter router() {
  return GoRouter(
    initialLocation: '/login',
    routes: [
      GoRoute(
        path: '/login',
        builder: (context, state) => const MyLogin(),
      ),
      GoRoute(
        path: '/catalog',
        builder: (context, state) => const MyCatalog(),
        routes: [
          GoRoute(
            path: 'cart',
            builder: (context, state) => const MyCart(),
          ),
        ],
      ),
    ],
  );
}

API 调用和配置示例

1. CatalogModel API

CatalogModel 提供商品目录数据的访问接口:

// 获取指定ID的商品
Item item = catalog.getById(1);

// 获取指定位置的商品
Item item = catalog.getByPosition(0);

2. CartModel API

CartModel 管理购物车的状态和操作:

// 添加商品到购物车
cart.add(item);

// 从购物车移除商品
cart.remove(item);

// 获取购物车中的所有商品
List<Item> items = cart.items;

// 获取购物车总价
int totalPrice = cart.totalPrice;

3. 在 Widget 中使用 Provider

3.1 监听状态变化

使用 context.watch 在 Widget 中监听状态变化:

class MyCatalog extends StatelessWidget {
  const MyCatalog({super.key});

  
  Widget build(BuildContext context) {
    // 监听 CatalogModel 的变化
    var catalog = context.watch<CatalogModel>();

    return Scaffold(
      appBar: AppBar(
        title: const Text('Catalog'),
        actions: [
          IconButton(
            icon: const Icon(Icons.shopping_cart),
            onPressed: () => Navigator.pushNamed(context, '/cart'),
          ),
        ],
      ),
      body: ListView.builder(
        itemCount: catalog.itemNames.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text(catalog.getByPosition(index).name),
            onTap: () {
              // 读取 CartModel 但不监听变化
              var cart = context.read<CartModel>();
              cart.add(catalog.getByPosition(index));
            },
          );
        },
      ),
    );
  }
}
3.2 使用 Consumer 优化性能

使用 Consumer 局部刷新 UI,提高性能:

class MyCart extends StatelessWidget {
  const MyCart({super.key});

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Cart'),
      ),
      body: Column(
        children: [
          Expanded(
            child: Consumer<CartModel>(
              builder: (context, cart, child) {
                return ListView.builder(
                  itemCount: cart.items.length,
                  itemBuilder: (context, index) {
                    return ListTile(
                      title: Text(cart.items[index].name),
                      trailing: IconButton(
                        icon: const Icon(Icons.remove),
                        onPressed: () {
                          cart.remove(cart.items[index]);
                        },
                      ),
                    );
                  },
                );
              },
            ),
          ),
          Consumer<CartModel>(
            builder: (context, cart, child) {
              return Text('Total: $${cart.totalPrice}');
            },
          ),
        ],
      ),
    );
  }
}

4. 鸿蒙平台适配

4.1 主题适配

确保应用主题与鸿蒙系统主题一致:

final appTheme = ThemeData(
  brightness: Brightness.light,
  primarySwatch: Colors.blue,
  visualDensity: VisualDensity.adaptivePlatformDensity,
);

// 或使用系统主题
MaterialApp(
  theme: appTheme,
  darkTheme: ThemeData.dark(),
  themeMode: ThemeMode.system,
  // ...
)
4.2 窗口配置

在鸿蒙设备上配置应用窗口大小:

void setupWindow() {
  if (!kIsWeb && Platform.isOHOS) {
    WidgetsFlutterBinding.ensureInitialized();
    // 鸿蒙平台窗口配置
  }
}

总结

Provider Shopper 是一个功能完整的 Flutter 应用示例,展示了如何使用 Provider 包进行高效的状态管理。通过这个应用,开发者可以学习:

  1. 基本 Provider 用法:如何创建和使用 Provider 提供不可变值
  2. 高级 Provider 用法:使用 ChangeNotifierProvider 管理可变状态,使用 ProxyProvider 处理依赖关系
  3. 状态共享:如何在应用的不同组件之间共享和更新状态
  4. 性能优化:如何使用 Consumercontext.select 优化状态监听
  5. 跨平台适配:如何适配鸿蒙平台等不同平台

Provider 包是 Flutter 中最流行的状态管理解决方案之一,它简单易用,适合各种规模的应用。通过学习这个示例,开发者可以快速掌握 Provider 的核心概念和最佳实践,为构建复杂的 Flutter 应用打下坚实的基础。

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

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐