精华内容
下载资源
问答
  • flutter provider
    2021-06-24 00:11:00

    Selector<A, S>

    相当于 Consumer 可以通过选择有限数量的值来过滤更新,并在它们没有更改时防止重建。
    Selector 将使用 Provider.of 获取一个值,然后将该值传递给 selector。然后,该selector回调的任务是返回一个对象,该对象仅包含builder所需的信息。

    Selector 源码:

    class Selector<A, S> extends Selector0<S> {
      /// {@macro provider.selector}
      Selector({
        Key? key,
        required ValueWidgetBuilder<S> builder,
        required S Function(BuildContext, A) selector,
        ShouldRebuild<S>? shouldRebuild,
        Widget? child,
      }) : super(
              key: key,
              shouldRebuild: shouldRebuild,
              builder: builder,
              selector: (context) => selector(context, Provider.of(context)),
              child: child,
            );
    }
    

    示例:

    这里使用了 mixin 混入了 ChangeNotifier,这个类能够帮驻我们自动管理所有听众。
    当调用 notifyListeners() 时,它会通知所有监听者进行刷新。

    import 'package:flutter/material.dart';
    
    class CountModel with ChangeNotifier {
      int _count = 0;
    
      int get count => _count;
    
      void increment() {
        _count++;
        notifyListeners();
      }
    }
    

    UI相关代码:
    value : 是下面 selector的返回值

     Selector<UserModel, int>(
                builder: (BuildContext context, value, Widget child) {
                  return Row(
                    children: [
                      child,
                      Text('$value'),
                    ],
                  );
                },
                selector: (BuildContext context, UserModel userModel) {
                  return userModel.count;
                },
                child: Text(['count:'),
              ),
    

    主要记录一下参数相关的东西:

    • A 指的是model , 或者叫provider (指with/extend ChangeNotifier的那个类),示例中的CountModel .
    • S selector参数中的返回类型 , 一般为 model中维护的数据 .
      如例子中的count的类型 int. 也可以是Wdiget, 比如你在这里返回一个Text, 就可以在builder中直接使用
                builder: (BuildContext context, value, Widget child) {
                  return Row(
                    children: [
                      child,
                      value,
                    ],
                  );
                },
                selector: (BuildContext context, UserModel userModel) {
                  return Text('${userModel.count}');
                },
    
    • typedef ValueWidgetBuilder<T> = Widget Function(BuildContext context, T value, Widget? child)
      T : selector的返回值的类型 , 其实是ValueWidgetBuilder<S>中的 S.
    • S Function(BuildContext, A) selector
      A : 同上文
    • typedef ShouldRebuild<T> = bool Function(T previous, T next)
      S : 同上文 ,其实是ShouldRebuild<S>? shouldRebuild中的S

    理解了以上这些概念,使用的时候就不会懵逼了 .

    Selector的好处 :

    • 减少UI重绘的部分, 提升性能 . 当监听到数据变更时, 只会重新调用builder.不会重绘更多UI部分.
    • 默认情况下,Selector通过使用来自包集合的 DeepCollectionEquality 比较Selector的先前和新结果来确定是否需要再次调用builder。(可以通过传递自定义的 shouldRebuild 回调来覆盖此行为。)
    更多相关内容
  • Flutter provider状态管理框架
  • Flutter Provider状态管理

    2022-06-15 14:26:44
    ProviderFlutter官方推出的状态管理包。 简单使用 读取值 监听数据 读取数据 必需继承类,否则无法刷新数据。

    Flutter Provider状态管理

    简述

    Provider是Flutter官方推出的状态管理包。

    添加库

    dependencies:
      provider: ^6.0.3
    

    简单使用

    读取值

    监听数据

    context.watch<CounterModel>().count;
    
    //等价于
    Provider.of<CounterModel>(context).count;
    

    读取数据

    context.read<CounterModel>().add();
    
    //等价于
    Provider.of<CounterModel>(context, listen: false).add();
    

    在这里插入图片描述

    定义数据管理类

    必需继承ChangeNotifier类,否则无法刷新数据。

    class CounterModel extends ChangeNotifier {
        int _count = 0;
    
        CounterModel(this._count);
    
        int get count => _count;
    
        void add() {
            _count++;
            notifyListeners();
        }
    }
    

    第一页

    class ProviderFirstPage extends StatefulWidget {
        const ProviderFirstPage({Key? key}) : super(key: key);
    
        @override
        State<StatefulWidget> createState() => _ProviderFirstPageState();
    }
    
    class _ProviderFirstPageState extends State<ProviderFirstPage> {
        @override
        Widget build(BuildContext context) {
            return Scaffold(
                appBar: AppBar(
                    title: const Text("Provider 第一页"),
                ),
                body: Center(
                    child: Column(
                        children: [
                            //监听数据变化
                            Text("${context.watch<CounterModel>().count}"),
                            ElevatedButton(
                                onPressed: () {
                                    Navigator.push(
                                        context,
                                        MaterialPageRoute(builder: (BuildContext context) {
                                            return const ProviderSecondPage();
                                        }),
                                    );
                                },
                                child: const Text("跳转第二页"),
                            ),
                        ],
                    ),
                ),
                floatingActionButton: FloatingActionButton(
                    child: const Icon(Icons.add),
                    onPressed: () {
                        //修改数据
                        context.read<CounterModel>().add();
                    },
                ),
            );
        }
    }
    

    第二页

    class ProviderSecondPage extends StatefulWidget {
        const ProviderSecondPage({Key? key}) : super(key: key);
    
        @override
        State<StatefulWidget> createState() => _ProviderSecondPageState();
    }
    
    class _ProviderSecondPageState extends State<ProviderSecondPage> {
        @override
        Widget build(BuildContext context) {
            return Scaffold(
                appBar: AppBar(
                    title: const Text("Provider 第二页"),
                ),
                body: Center(
                    child: Column(
                        children: [
                            //监听数据变化
                            Text("${Provider.of<CounterModel>(context).count}"),
                            ElevatedButton(
                                onPressed: () {
                                    Navigator.pop(context);
                                },
                                child: const Text("返回"),
                            ),
                        ],
                    ),
                ),
                floatingActionButton: FloatingActionButton(
                    child: const Icon(Icons.add),
                    onPressed: () {
                        //修改数据
                        Provider.of<CounterModel>(context, listen: false).add();
                    },
                ),
            );
        }
    }
    

    注册单个状态管理类

    void main() {
        runApp(
            ChangeNotifierProvider(
                create: (context) => CounterModel(0),
                child: const MyApp(),
            ),
        );
    }
    

    注册多个状态管理类

    void main() {
        runApp(
            MultiProvider(
                providers: [
                    ChangeNotifierProvider(create: (context) => CounterModel(0)),
                ],
                child: const MyApp(),
            ),
        );
    }
    
    展开全文
  • Flutter Provider局部刷新

    2021-06-22 17:37:26
    1.添加Provider依赖 dependencies: provider: ^4.0.4 flutter: sdk: flutter 最新版本https://pub.dev/packages/provider 2.创建ProviderModel class FirstProviderModel extends ChangeNotifier{ int _count =...

    1.添加Provider依赖

    dependencies:
      provider: ^4.0.4
      flutter:
        sdk: flutter
    

    最新版本https://pub.dev/packages/provider

    2.创建ProviderModel

    class FirstProviderModel extends ChangeNotifier{
      int _count = 0;
    
      int get count => _count;
    
      void add() {
        _count++;
        print('$_count');
        notifyListeners();
      }
    }
    

    这是一个计数案例,_count属于私有化只能通过count调用、add是增加数值方法。

    3.使用前需要注册ProviderModel
    (1)单页面使用注册

    ///用来配置页面中的Provider
    ///仅当前页面使用
    class FirstProviderStateless extends StatelessWidget{
      @override
      Widget build(BuildContext context) {
        return  MultiProvider(
          providers: [
            ChangeNotifierProvider(create: (_)=>FirstProviderModel()),
          ],
          child: FirstProvider(),
        );
      }
    }
    

    (2)多页面使用注册(在main.dart中)

    ///MultiProvider配置在main里面才可以在页面之间通用
    ///配置在单个页面当中 数据不会刷新
    main() {
      runApp(MultiProvider(
          providers: [
            ChangeNotifierProvider(create: (_)=>FirstProviderModel())
        ],
        child: MyApp(),
      ));
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        return MaterialApp(
          home: FirstProvider(),
        );
      }
    }
    
    

    两者区别:
    单页面使用仅仅只是为了局部刷新使用。
    多页面使用注册是为了多个页面改变值使用(例如A和B两个页面,a页面负责展示值 b页面既展示又要去修改这个值,这时在b页面修改值之后也会通知a页面的值进行改变)

    4.注册完成之后如何局部刷新
    想要达到局部刷新效果需要将要刷新的控件放在Consumer当中代码展示如下

    
    class FirstProvider extends StatefulWidget{
      @override
      State<StatefulWidget> createState() {
        return FirstProviderState();
      }
    }
    
    class FirstProviderState extends State<FirstProvider>{
      ///刷新次数记录
      var _refreshTime = 0;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(title: Text('FirstProvider')),
            body:  getColumn(),
    
            floatingActionButton: FloatingActionButton(
              onPressed: (){
       
                //这句是为了修改model当中的值 当前直接进行修改值。
              	Provider.of<FirstProviderModel>(context,listen: false).add();
              	//这句是为了跳转下一个页面 完善两个页面共用一个值的需求。
                //Navigator.push(context, MaterialPageRoute(builder: (context) => SecondProvider()));
              },
              child: Icon(Icons.navigate_next),
            ),
        );
      }
    
      getColumn(){
        _refreshTime ++;
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisSize: MainAxisSize.max,
          children: [
            ///包裹在Consumer中 才可以局部刷新这块
            Consumer<FirstProviderModel>(
              builder: (context, counter, child) => Text(
                '同步second页面值:${counter.count}',
              ),
            ),
    
            ///为了证明这里没刷新  刷新的话数值增加
            Container(
              alignment: Alignment.topCenter,
              child: Text('记录当前页面刷新次数:${_refreshTime}'),
            )
          ],
        );
      }
    
    

    如上代码可以看出就需要局部刷新控件是放在Consumer当中,_refreshTime是为了标记在局部刷新时没有刷新其他控件。
    counter相当于是最开始创建的ProviderModel

    floatingActionButton跳转的是可点击增加计数的页面SecondProvider

    
    class SecondProvider extends StatefulWidget{
      @override
      State<StatefulWidget> createState() {
        return SecondProviderState();
      }
    }
    
    class SecondProviderState extends State<SecondProvider>{
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('SecondProvider')),
          body: Center(
            child: Text('同步First页面值:${Provider.of<FirstProviderModel>(context).count}'),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: (){
              Provider.of<FirstProviderModel>(context,listen: false).add();
            },
            child: Icon(Icons.add),
          ),
        );
      }
    
    }
    

    通过Provider.of<FirstProviderModel>(context,listen: false).add();对model当中的数值进行修改。

    完成代码
    main.dart页面

    ///MultiProvider配置在main里面才可以在页面之间通用
    ///配置在单个页面当中 数据不会刷新
    main() {
      runApp(MultiProvider(
          providers: [
            ChangeNotifierProvider(create: (_)=>FirstProviderModel())
        ],
        child: MyApp(),
      ));
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        return MaterialApp(
          home: FirstProvider(),
        );
      }
    }
    
    

    FirstProvider

    ///用来配置页面中的Provider
    ///仅当前页面使用
    class FirstProviderStateless extends StatelessWidget{
      @override
      Widget build(BuildContext context) {
        return  MultiProvider(
          providers: [
            ChangeNotifierProvider(create: (_)=>FirstProviderModel()),
          ],
          child: FirstProvider(),
        );
      }
    }
    
    
    class FirstProvider extends StatefulWidget{
      @override
      State<StatefulWidget> createState() {
        return FirstProviderState();
      }
    }
    
    class FirstProviderState extends State<FirstProvider>{
      ///刷新次数记录
      var _refreshTime = 0;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(title: Text('FirstProvider')),
            body:  getColumn(),
    
            floatingActionButton: FloatingActionButton(
              onPressed: (){
                Navigator.push(context, MaterialPageRoute(builder: (context) => SecondProvider()));
              },
              child: Icon(Icons.navigate_next),
            ),
        );
      }
    
      getColumn(){
        _refreshTime ++;
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisSize: MainAxisSize.max,
          children: [
            ///包裹在Consumer中 才可以局部刷新这块
            Consumer<FirstProviderModel>(
              builder: (context, counter, child) => Text(
                '同步second页面值:${counter.count}',
              ),
            ),
    
            ///为了证明这里没刷新  刷新的话数值增加
            Container(
              alignment: Alignment.topCenter,
              child: Text('记录当前页面刷新次数:${_refreshTime}'),
            )
          ],
        );
      }
    
    }
    
    

    SecondProvider

    
    
    ///用来配置页面中的Provider
    ///仅当前页面使用
    class SecondStateless extends StatelessWidget{
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        return MultiProvider(
          providers: [
            ChangeNotifierProvider(create: (_) => FirstProviderModel()),
          ],
          child: SecondProvider(),
        );
      }
    
    }
    class SecondProvider extends StatefulWidget{
      @override
      State<StatefulWidget> createState() {
        return SecondProviderState();
      }
    }
    
    class SecondProviderState extends State<SecondProvider>{
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('SecondProvider')),
          body: Center(
            child: Text('同步First页面值:${Provider.of<FirstProviderModel>(context).count}'),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: (){
              Provider.of<FirstProviderModel>(context,listen: false).add();
            },
            child: Icon(Icons.add),
          ),
        );
      }
    
    }
    
    
    

    以上就是本文全部内容,如有错误还请大家多多指正。

    展开全文
  • flutter Provider 购物车功能

    千次阅读 2022-04-11 20:52:11
    使用Provider实现购物功能 下面这个demo来自flutter官网,有兴趣的小伙伴可以去看看原文。 https://flutter.cn/docs/development/data-and-backend/state-mgmt/simple main.dart文件 import 'package:flutter/...

    使用Provider实现购物功能

    下面这个demo来自flutter官网,有兴趣的小伙伴可以去看看原文。

    https://flutter.cn/docs/development/data-and-backend/state-mgmt/simple

    效果如下:
    在这里插入图片描述

    main.dart文件

    import 'package:flutter/foundation.dart';
    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({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        // 提供多个对象时使用 MultiProvider 很方便。
        return MultiProvider(
          providers: [
            // 在这个示例应用程序中,CatalogModel 永远不会改变,所以一个简单的 Provider 就足够了。
            Provider(create: (context) => CatalogModel()),
            // CartModel 实现为 ChangeNotifier,它要求使用 ChangeNotifierProvider。
            // 此外,CartModel 依赖于 CatalogModel,
            // 因此需要一个 ProxyProvider。
            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: '/',
            routes: {
              '/': (context) => const MyLogin(),
              '/catalog': (context) => const MyCatalog(),
              '/cart': (context) => const MyCart(),
            },
          ),
        );
      }
    }
    
    

    models\cart.dart文件

    import 'package:flutter/foundation.dart';
    import 'package:provider_shopper/models/catalog.dart';
    
    class CartModel extends ChangeNotifier {
      /// 支持 [目录] 的私有字段。
      late CatalogModel _catalog;
    
      /// 购物车的内部私有状态。存储每个项目的 ID。
      final List<int> _itemIds = [];
    
      /// 当前目录。用于从数字 id 构造项目。
      CatalogModel get catalog => _catalog;
    
      set catalog(CatalogModel newCatalog) {
        _catalog = newCatalog;
        // 通知听众,以防新目录提供的信息与以前的不同。
        // 例如,项目的可用性可能已更改。
        notifyListeners();
      }
    
      /// List of items in the cart.
      List<Item> get items => _itemIds.map((id) => _catalog.getById(id)).toList();
    
      /// 所有商品的当前总价。
      int get totalPrice =>
          items.fold(0, (total, current) => total + current.price);
    
      /// 将 [item] 添加到购物车。这是从外部修改购物车的唯一方法。
      void add(Item item) {
        _itemIds.add(item.id);
        // 这一行告诉 [Model] 它应该重建依赖它的小部件。
        notifyListeners();
      }
    
      void remove(Item item) {
        _itemIds.remove(item.id);
        // 每次更改模型时,不要忘记告诉依赖的小部件重新构建。
        notifyListeners();
      }
    }
    

    models\catalog.dart文件

    import 'package:flutter/material.dart';
    
    /// 用户可以购买的商品目录的代理。
    ///
    /// 在真实的应用程序中,这可能由后端支持并缓存在设备上。
    /// 在这个示例应用程序中,目录是程序生成的并且是无限的。
    ///
    /// 为简单起见,目录应该是不可变的(在应用程序执行期间不希望添加、删除或更改任何产品)。
    class CatalogModel {
      static List<String> itemNames = [
        'Code Smell',
        'Control Flow',
        'Interpreter',
        'Recursion',
        'Sprint',
        'Heisenbug',
        'Spaghetti',
        'Hydra Code',
        'Off-By-One',
        'Scope',
        'Callback',
        'Closure',
        'Automata',
        'Bit Shift',
        'Currying',
      ];
    
      /// 通过 [id] 获取项目。
      ///
      /// 在此示例中,目录是无限的,在 [itemNames] 上循环。
      Item getById(int id) => Item(id, itemNames[id % itemNames.length]);
    
      /// 通过其在目录中的位置获取项目。
      Item getByPosition(int position) {
        // 在这个简化的例子中,一个项目在目录中的位置也是它的 id。
        return getById(position);
      }
    }
    
    @immutable
    class Item {
      final int id;
      final String name;
      final Color color;
      final int price = 42;
    
      Item(this.id, this.name)
      // 为了使示例应用程序看起来更好,每个项目都被赋予了一种 Material Design 原色。
          : color = Colors.primaries[id % Colors.primaries.length];
    
      @override
      int get hashCode => id;
    
      @override
      bool operator ==(Object other) => other is Item && other.id == id;
    }
    

    screens\cart.dart文件

    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    import 'package:provider_shopper/models/cart.dart';
    
    class MyCart extends StatelessWidget {
      const MyCart({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Cart', style: Theme.of(context).textTheme.headline1),
            backgroundColor: Colors.white,
          ),
          body: Container(
            color: Colors.yellow,
            child: Column(
              children: [
                Expanded(
                  child: Padding(
                    padding: const EdgeInsets.all(32),
                    child: _CartList(),
                  ),
                ),
                const Divider(height: 4, color: Colors.black),
                _CartTotal()
              ],
            ),
          ),
        );
      }
    }
    
    class _CartList extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        var itemNameStyle = Theme.of(context).textTheme.headline6;
        // This gets the current state of CartModel and also tells Flutter
        // to rebuild this widget when CartModel notifies listeners (in other words,
        // when it changes).
        var cart = context.watch<CartModel>();
    
        return ListView.builder(
          itemCount: cart.items.length,
          itemBuilder: (context, index) => ListTile(
            leading: const Icon(Icons.done),
            trailing: IconButton(
              icon: const Icon(Icons.remove_circle_outline),
              onPressed: () {
                cart.remove(cart.items[index]);
              },
            ),
            title: Text(
              cart.items[index].name,
              style: itemNameStyle,
            ),
          ),
        );
      }
    }
    
    class _CartTotal extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        var hugeStyle =
        Theme.of(context).textTheme.headline1!.copyWith(fontSize: 48);
    
        return SizedBox(
          height: 200,
          child: Center(
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                // 侦听模型更改的另一种方法是包含 Consumer 小部件。
                // 此小部件将自动侦听 CartModel 并在每次更改时重新运行其构建器。
                //
                // 重要的是它不会在此构建方法中重建其余的小部件。
                Consumer<CartModel>(
                    builder: (context, cart, child) =>
                        Text('\$${cart.totalPrice}', style: hugeStyle)),
                const SizedBox(width: 24),
                TextButton(
                  onPressed: () {
                    ScaffoldMessenger.of(context).showSnackBar(
                        const SnackBar(content: Text('Buying not supported yet.')));
                  },
                  style: TextButton.styleFrom(primary: Colors.white),
                  child: const Text('BUY'),
                ),
              ],
            ),
          ),
        );
      }
    }
    

    screens\catalog.dart文件

    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    import 'package:provider_shopper/models/cart.dart';
    import 'package:provider_shopper/models/catalog.dart';
    
    class MyCatalog extends StatelessWidget {
      const MyCatalog({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: CustomScrollView(
            slivers: [
              _MyAppBar(),
              const SliverToBoxAdapter(child: SizedBox(height: 12)),
              SliverList(
                delegate: SliverChildBuilderDelegate(
                    (context, index) => _MyListItem(index)),
              ),
            ],
          ),
        );
      }
    }
    
    class _AddButton extends StatelessWidget {
      final Item item;
    
      const _AddButton({required this.item, Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        // context.select() 方法可以让你监听模型一部分的变化。
        // 您定义一个“选择”(即返回)您感兴趣的部分的函数,并且提供程序包不会重建此小部件,
        // 除非模型的特定部分发生更改。
        //
        // 这可以导致显着的性能改进。
        var isInCart = context.select<CartModel, bool>(
          // Here, we are only interested whether [item] is inside the cart.
          (cart) => cart.items.contains(item),
        );
    
        return TextButton(
          onPressed: isInCart
              ? null
              : () {
                  // 如果商品不在购物车中,我们让用户添加它。
                  // 我们在这里使用 context.read() ,因为每当用户点击按钮时都会执行回调。
                  // 换句话说,它是在 build 方法之外执行的。
                  var cart = context.read<CartModel>();
                  cart.add(item);
                },
          style: ButtonStyle(
            overlayColor: MaterialStateProperty.resolveWith<Color?>((states) {
              if (states.contains(MaterialState.pressed)) {
                return Theme.of(context).primaryColor;
              }
              return null; // 遵循小部件的默认设置。
            }),
          ),
          child: isInCart
              ? const Icon(Icons.check, semanticLabel: 'ADDED')
              : const Text('ADD'),
        );
      }
    }
    
    class _MyAppBar extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return SliverAppBar(
          title: Text('Catalog', style: Theme.of(context).textTheme.headline1),
          floating: true,
          actions: [
            IconButton(
              icon: const Icon(Icons.shopping_cart),
              onPressed: () => Navigator.pushNamed(context, '/cart'),
            ),
          ],
        );
      }
    }
    
    class _MyListItem extends StatelessWidget {
      final int index;
    
      const _MyListItem(this.index, {Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        var item = context.select<CatalogModel, Item>(
          // 在这里,我们只对 [index] 处的项目感兴趣。我们不关心任何其他变化。
          (catalog) => catalog.getByPosition(index),
        );
        var textTheme = Theme.of(context).textTheme.headline6;
    
        return Padding(
          padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
          child: LimitedBox(
            maxHeight: 48,
            child: Row(
              children: [
                AspectRatio(
                  aspectRatio: 1,
                  child: Container(
                    color: item.color,
                  ),
                ),
                const SizedBox(width: 24),
                Expanded(
                  child: Text(item.name, style: textTheme),
                ),
                const SizedBox(width: 24),
                _AddButton(item: item),
              ],
            ),
          ),
        );
      }
    }
    
    

    login.dart

    import 'package:flutter/material.dart';
    
    class MyLogin extends StatelessWidget {
      const MyLogin({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: Container(
              padding: const EdgeInsets.all(80.0),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(
                    'Welcome',
                    style: Theme.of(context).textTheme.headline1,
                  ),
                  TextFormField(
                    decoration: const InputDecoration(
                      hintText: 'Username',
                    ),
                  ),
                  TextFormField(
                    decoration: const InputDecoration(
                      hintText: 'Password',
                    ),
                    obscureText: true,
                  ),
                  const SizedBox(
                    height: 24,
                  ),
                  ElevatedButton(
                    child: const Text('ENTER'),
                    onPressed: () {
                      Navigator.pushReplacementNamed(context, '/catalog');
                    },
                    style: ElevatedButton.styleFrom(
                      primary: Colors.yellow,
                    ),
                  )
                ],
              ),
            ),
          ),
        );
      }
    }
    

    theme.dart

    import 'package:flutter/material.dart';
    
    final appTheme = ThemeData(
      primarySwatch: Colors.yellow,
      textTheme: const TextTheme(
        headline1: TextStyle(
          fontFamily: 'Corben',
          fontWeight: FontWeight.w700,
          fontSize: 24,
          color: Colors.black,
        ),
      ),
    );
    
    展开全文
  • Flutter Provider状态管理-Consumer

    千次阅读 2020-06-08 08:41:31
    如果对Consumer很了解的同学可以继续学习Flutter Provider状态管理 - Selector 个人觉得Flutter的学习有三个很重要的阶段 widget的学习和使用 数据以及状态的管理 和原生的交互 对于第一点不必多说,大家开始学习...
  • 如果你还不了解Consumer,请移步我的上一篇博文,Flutter Provider状态管理-Consumer,此篇文章是基于上一篇的基础来的。 从上一篇中我们知道Consumer可以实现UI页面的局部刷新,摒弃掉传统的setState,让UI的表现...
  • Flutter Provider 原理解析

    千次阅读 2022-02-10 21:10:43
    Flutter Provider的主要功能 数据共享 局部刷新 要实现以上两个功能点,首先要来了解一下Flutter中的InheritedWidget InheritedWidget简介 Flutter Widget 简介 Everything is a widget. Widget是『描述』 ...
  • Flutter Provider状态管理的八种提供者、四种消费者(上)
  • provider: 状态管理来管理统一的状态(数据),实现不同组件直接的传值和数据共享。 eventBus: 现不同组件之间的数据传值,以及在一个组件中 执行另一个组件的方法。
  • 题记 —— 执剑天涯,从你的点滴积累开始,所及之处,必精益求精。 Flutter是谷歌推出的最新的移动开发框架。...Provider ( 就是本文了) ValueNotifier 点击查看详情 Stream 流(StreamController ) EventBus 正在
  • 由于项目封装,App外部还有一个ConfigApp类,App注册一个BaseConfig到Provider中.ConfigApp类中有BaseConfig的实现.直接用BaseConfig的子类调用notifyListeners()刷新无效.结构如下: 然后子类AppConfig实现...
  • Flutter Provider使用指南

    千次阅读 2020-06-08 09:13:55
    在大热的跨端框架flutter中,笔者将对社区中使用广泛的provider框架进行介绍。 准备工作 安装与引入 provider pub链接 官方文档宣称(本文基于4.0版本),provider是一个依赖注入和状态管理的混合工具,通过组件来...
  • Flutter Provider状态管理的八种提供者、四种消费者(下)
  • Flutter -黑夜/白天模式 1.简介 黑夜/白天模式,在App中非常常见,那么如何通过Flutter来修改主题了 2.Theme theme: ThemeData( brightness: _isLight == true ? Brightness.light : Brightness.dark //判断 夜间...
  • 大家好,我是学习Flutter好几个月的 张信哲 ,熟练使用CV大法。
  • 如果对Consumer很了解的同学可以继续学习Flutter Provider状态管理 - Selector个人觉得Flutter的学习有三个很重要的阶段1.widget的学习和使用2.数据以及状态的管理3.和原生的交互对于第一点不必多说,大家开始学习...
  • 安装Provider库:pubspec.yaml文件 dependencies: flutter: sdk: flutter ... provider: ^4.1.3 注册Provider: main.dart文件: void main() { runApp( //注册Provider MultiProvider( providers: [ ...
  • flutter Provider状态管理

    千次阅读 2021-12-22 15:51:03
    flutter provider跨组件状态共享的简单使用 provider是对InheritedWidget进行封装的,官方介绍有简化资源分配,懒加载,创建新类时减少大量的模板代码,支持DevTools,提升类的可扩展性,整体监听架构时间复杂度以及...
  • flutter provider状态管理

    2021-03-22 21:12:09
    https://flutter.cn/docs/development/data-and-backend/state-mgmt/simple
  • flutter_provider本教程的项目源码,欢迎star 为什么需要状态管理 在进行项目的开发时,我们往往需要管理不同页面之间的数据共享,在页面功能复杂,状态达到几十个上百个的时候,我们会难以清楚的维护我们的数据...
  • Flutter Provider框架实战

    2021-06-23 21:18:06
    Provider 框架实际应用
  • Flutter provider劝退经历

    千次阅读 2020-10-22 15:57:59
    最近在学习Flutter中的状态管理用到provider时,原本以为按着文档的简单示例写一点问题都没有,结果惨遭各种翻车,整个屏幕宛如一片红海,因此,写下该篇文章,记录学习。那现在就开始吧。 使用Provider 这里先使用...
  • }, ) 修改数据更新UI list.value[index].name = 'Flutter'; list.update(); notifyListeners(); 或者 list.value= [UserModel(name: "Flutter", email: "123@xxx.com")]; notifyListeners(); 增加 list.add...
  • Flutter Provider源码分析

    2022-03-11 20:03:01
    阅读此文的彦祖,亦菲们,附送一枚Provider模板代码生成插件! 我为啥要写这个插件呢? 此事说来话短,我这不准备写解析Provider源码的文章,肯定要写这框架的使用样例啊,然后再哔哔源码呀!在写demo样例的时候...
  • flutter provider

    2022-02-15 15:36:50
    flutter provider前提需知InheritedWidget 前提需知 InheritedWidget 它是一个功能性组件,它提供了widget树中从上到下共享数据的方式,我们可以在widget的根组件中写数据那么在任意组件中都可以调用了,比如共享...
  • flutter provider4.1.2的坑,报错处理

    千次阅读 2020-05-22 10:50:19
    直接看关键代码:Provider.of without passing `listen: false`. 就是因为provider4.1.2版本调用时,因为你没传listen:false,禁止监听,引发没必要更新, 具体在哪儿,下面会提示,比如我这截图是typePage.dart, ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,126
精华内容 1,650
关键字:

flutter provider