Flutter中Provider的一般用法(一)

在flutter中Provider是比较常用的Widget, Provider通常用来管理value的生命周期,通过Create和Dispose,它们是成对出现的,可以在Create进行value的初始化操作,在dispose进行value的释放操作。使用Provider可以避免一些琐碎的操作,比如实例化一个BLoC操作,事实上,Provider等效于状态管理类State.initState和State.dispose的组合,Create只会在State.initState中调用一次。我们不能直接使用InheritedWidget,因为它需要构造函数已初始化,并且为最终值。

下面是一个例子,初始化一次Model,并且当Provider从数中被移除的时候,dispose会被调用:

 class Model {
   void dispose() {}
 }
 class Stateless extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     return Provider<Model>(
       create: (context) =>  Model(),
       dispose: (context, value) => value.dispose(),
       child: ...,
     );
   }
 }

'create'回调是懒加载式的,只有第一次获取value的时候才会被调用,而不是在provider第一次被插入到widget树中的时候调用。当然,这个行为是可以被禁用的,通过设置Provider的"lazy:false"。

Provider提供了几种获取实例的方式:

 Provider({
    Key key,
    @required Create<T> create,
    Dispose<T> dispose,
    bool lazy,
    TransitionBuilder builder,
    Widget child,
  })  : assert(create != null),
        super(
          key: key,
          lazy: lazy,
          builder: builder,
          create: create,
          dispose: dispose,
          debugCheckInvalidValueType: kReleaseMode
              ? null
              : (T value) =>
                  Provider.debugCheckInvalidValueType?.call<T>(value),
          child: child,
        );

这中方式可以创建一个value,并且存储它,和暴露给它的后代,value可以选择性在dispose回调中释放,dispose会在Provider从树中移出的时候被调用。

Provider.value({
    Key key,
    @required T value,
    UpdateShouldNotify<T> updateShouldNotify,
    TransitionBuilder builder,
    Widget child,
  })  : assert(() {
          Provider.debugCheckInvalidValueType?.call<T>(value);
          return true;
        }()),
        super.value(
          key: key,
          builder: builder,
          value: value,
          updateShouldNotify: updateShouldNotify,
          child: child,
        );

这中方式暴露一个已存在的不用释放的值,其中可选参数updateShouldNotify可以用来控制是否需要重绘,当value值改变的时候,一般来说(previous, next) => previous != next时,会重绘。

static T of<T>(BuildContext context, {bool listen = true}) 

这个静态方法可以获取widget树中最近的Provider<T>,并且返回它的值。如果listen为true,那么随后value发生的变化会触发State.build和State.didChangeDependencies. 如果需要在initState中调用Provider.of或者如下调用Provider的create方法时,需要设置listen为false:

Provider(
  create: (context) {
    return Model(Provider.of<Something>(context, listen: false)),
  },
)

如果试图在widget树外监听Provider暴露出来的值,也需要设置listen为false,比如在点击事件中调用,否则的话可能会导致跟事件句柄关联的wieget重建,如果这个widget并不在意这个value的话。

 

讲到Provider的用法,我们还需了解MultiProvider, 一般来说,MultiProvider用于单个线性widget树中,可以增强可读性和减少多层嵌套的样板代码,如下:
 

Provider<Something>(
  create: (_) => Something(),
  child: Provider<SomethingElse>(
    create: (_) => SomethingElse(),
    child: Provider<AnotherThing>(
      create: (_) => AnotherThing(),
      child: someWidget,
    ),
  ),
),

使用MultiProvider则可以简化为:

MultiProvider(
  providers: [
    Provider<Something>(create: (_) => Something()),
    Provider<SomethingElse>(create: (_) => SomethingElse()),
    Provider<AnotherThing>(create: (_) => AnotherThing()),
  ],
  child: someWidget,
)

这两种方式是等效的。下面我们看下MultiProvider的构造方法:

MultiProvider({
    Key key,
    @required List<SingleChildWidget> providers,
    Widget child,
    TransitionBuilder builder,
  })  : assert(providers != null),
        super(
          key: key,
          children: providers,
          child: builder != null
              ? Builder(
                  builder: (context) => builder(context, child),
                )
              : child,
        );

参数builder是个语法糖,用来获取BuildContext,可以用它来获取创建的providers:

MultiProvider(
  providers: [
    Provider<Something>(create: (_) => Something()),
    Provider<SomethingElse>(create: (_) => SomethingElse()),
    Provider<AnotherThing>(create: (_) => AnotherThing()),
  ],
  builder: (context, child) {
    final something = context.watch<Something>();
    return Text('$something');
  },
)

等效于

MultiProvider(
  providers: [
    Provider<Something>(create: (_) => Something()),
    Provider<SomethingElse>(create: (_) => SomethingElse()),
    Provider<AnotherThing>(create: (_) => AnotherThing()),
  ],
  child: Builder(
    builder: (context) {
      final something = context.watch<Something>();
      return Text('$something');
    },
  ),
)

上面两种方式是等效的。当providers中存在provider有child widget的,将会被忽略,下面两种方式是等效的:

MultiProvider(
  providers: [
    Provider<Something>(create: (_) => Something(), child: SomeWidget()),
  ],
  child: Text('Something'),
)

等效:
MultiProvider(
  providers: [
    Provider<Something>(create: (_) => Something()),
  ],
  child: Text('Something'),
)

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
FlutterProvider是一个状态管理工具,它可以帮助我们在应用程序共享数据。 使用Provider的步骤如下: 1. 引入Provider包 在项目的pubspec.yaml文件加入provider包的依赖: ``` dependencies: flutter: sdk: flutter provider: ^4.3.2+2 ``` 2. 创建数据模型 在使用Provider之前,需要先定义一个数据模型。这个数据模型可以是一个类,也可以是一个数据结构。 例如,我们可以定义一个名为“CountModel”的数据模型,用于存储计数器的值: ``` class CountModel extends ChangeNotifier { int _count = 0; int get count => _count; void increment() { _count++; notifyListeners(); } } ``` 在这个模型,我们定义了一个私有变量_count,用于存储计数器的值。我们还定义了一个公共的getter方法count,用于获取计数器的值。最后,我们定义了一个increment方法,用于将计数器的值加1,并通过notifyListeners通知依赖该模型的组件进行更新。 3. 在组件使用Provider 在组件使用Provider非常简单。我们可以使用Provider.of方法来获取数据模型,并在组件使用该数据模型。 例如,我们可以创建一个名为“CounterPage”的页面,用于显示计数器的值和一个按钮,用于增加计数器的值: ``` class CounterPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Counter'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( 'Counter', ), Consumer<CountModel>( builder: (context, countModel, child) { return Text( '${countModel.count}', style: Theme.of(context).textTheme.headline4, ); }, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () { Provider.of<CountModel>(context, listen: false).increment(); }, tooltip: 'Increment', child: Icon(Icons.add), ), ); } } ``` 在这个页面,我们使用Consumer来获取CountModel数据模型,并在Text组件显示计数器的值。我们还使用Provider.of方法来获取CountModel数据模型,并在FloatingActionButton组件使用increment方法来增加计数器的值。 这就是使用Provider的基本步骤。需要注意的是,Provider.of方法会向上查找widget树,直到找到对应的Provider对象。因此,我们需要在应用程序的根组件创建Provider对象,以便在整个应用程序共享数据模型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

释汐宇辰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值