美文网首页
Flutter的状态管理-Provider简单使用

Flutter的状态管理-Provider简单使用

作者: 三国韩信 | 来源:发表于2022-11-13 20:18 被阅读0次
Provider的几种使用方式

1、Provider
描述:是为恒定的数据提供的方法(类)。当一个widget只是从这个model中取数据,而不去监听数据的变化而去重绘界面.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class MyModel {
  MyModel({this.counter = 0});
  int counter = 0;
  void incrementCounter() {
    counter++;
    print(counter);
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("build方法来了");
    return Provider(
      create: (_) => MyModel(),
      child: Scaffold(
        appBar: AppBar(
          title: Text('provider'),
        ),
        body: Column(
          children: <Widget>[
            Builder(
              builder: (context) {
                // 获取到provider提供出来的值
                MyModel _model = Provider.of<MyModel>(context, listen: false);
                return Container(
                    margin: const EdgeInsets.only(top: 20),
                    width: MediaQuery.of(context).size.width,
                    padding: const EdgeInsets.all(20),
                    alignment: Alignment.center,
                    color: Colors.lightBlueAccent,
                    child: Text('当前是:${_model.counter}'));
              },
            ),
            Consumer<MyModel>(
              // 获取到provider提供出来的值
              builder: (context, model, child) {
                return Container(
                  margin: const EdgeInsets.only(top: 20),
                  width: MediaQuery.of(context).size.width,
                  padding: const EdgeInsets.all(20),
                  alignment: Alignment.center,
                  color: Colors.lightGreen,
                  child: Text(
                    '${model.counter}',
                  ),
                );
              },
            ),
            Consumer<MyModel>(
              // 获取到provider提供出来的值
              builder: (context, model, child) {
                return FlatButton(
                    color: Colors.tealAccent,
                    onPressed: model.incrementCounter,
                    child: Icon(Icons.add));
              },
            ),
          ],
        ),
      ),
    );
  }
}

2、ListenableProvider和ChangeNotifierProvider
描述:当model对像中有数据变化时,需要触发widget中的元素重绘,实现数据驱动,这时我们需要用到ChangeNotifierProvider。

import 'package:flutter/material.dart';
import 'package:flutterproviderapp/detailPage.dart';
import 'package:provider/provider.dart';
import 'Models.dart';

class MyHomePage2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("MyHomePage2的build方法来了");
    return ListenableProvider(
      /* ListenableProvider和ChangeNotifierProvider几乎是一样的效果,只是ListenableProvider比ChangeNotifierProvider多了个_dispose函数,
      会在适当的时候自动销毁,一般情况下只用changeNotifierProvider即可。
      */
      create: (_) => MyModel(),
      child: Scaffold(
        appBar: AppBar(
          title: Text('ChangeNotifierProvider'),
        ),
        body: Column(
          children: <Widget>[
            Builder(
              builder: (context) {
                // 获取到provider提供出来的值
                MyModel _model = Provider.of<MyModel>(context, listen: false);
                return Container(
                    margin: const EdgeInsets.only(top: 20),
                    width: MediaQuery.of(context).size.width,
                    padding: const EdgeInsets.all(20),
                    alignment: Alignment.center,
                    color: Colors.lightBlueAccent,
                    child: Text('当前是:${_model.counter}'));
              },
            ),
            Consumer<MyModel>(
              // 获取到provider提供出来的值
              child: Container(
                // consumer 里的child的组件是不会被渲染的,builder里的组件是会被重新渲染的
                margin: const EdgeInsets.only(top: 20),
                width: MediaQuery.of(context).size.width,
                padding: const EdgeInsets.all(20),
                alignment: Alignment.center,
                color: Colors.lightGreen,
                child: Text(
                  'hhhhhhhhhhh',
                ),
              ),
              builder: (context, model, child) {
                print("Consumer里的builder来了");
                return Column(
                  children: <Widget>[
                    child!,
                    Container(
                      margin: const EdgeInsets.only(top: 20),
                      width: MediaQuery.of(context).size.width,
                      padding: const EdgeInsets.all(20),
                      alignment: Alignment.center,
                      color: Colors.lightGreen,
                      child: Text(
                        '${model.counter}',
                      ),
                    )
                  ],
                );
              },
            ),
            MyText(),
            MyText2(),
            Consumer<MyModel>(
              // 获取到provider提供出来的值
              builder: (context, model, child) {
                return FlatButton(
                    color: Colors.tealAccent,
                    onPressed: model.incrementCounter,
                    child: Icon(Icons.add));
              },
            ),
          ],
        ),
      ),
    );
  }
}

// 初始化一个单独的子部件套进去,看能不能用provider.of(context)获取model
class MyText extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("MyText子部件的build方法来了");
    MyModel _model =
        Provider.of<MyModel>(context); // 这里的也能正常拿到Provider中的model的,因为是共享的。
    return Container(
      child: Text('当前是MyText里的:${_model.counter}'),
    );
  }
}

class MyText2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("MyText2子部件的build方法来了");
    MyModel models =
        Provider.of<MyModel>(context); // 这里的也能正常拿到Provider中的model的,因为是共享的。
    return Container(
      child: FlatButton(
          color: Colors.tealAccent,
          onPressed: () {
            Navigator.of(context).push(MaterialPageRoute(builder: (context) {
              return DiscoverDetailPage(models);
            }));
          },
          child: Icon(Icons.ac_unit)),
    );
  }
}

例子中使用到的model

import 'package:flutter/material.dart';
class MyModel with ChangeNotifier {
  MyModel({this.counter = 0});
  int counter = 0;
  void incrementCounter() {
    counter++;
    print(counter);
    notifyListeners();
  }
}

3、StreamProvider
描述:可以给StreamProvider提供一份初始的数据Model,通过给StreamProvider设置了一个每隔1秒更新一次的stream,ui上的计数值也是每隔一秒改变一次。

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class MyModel with ChangeNotifier {
  MyModel({this.counter = 0});
  int counter = 0;
  void incrementCounter() {
    counter++;
    print(counter);
    notifyListeners();
  }
}

class MyHomePage4 extends StatelessWidget {
  Stream<MyModel> getStreamProviderData(BuildContext context) {
    print("getStreamProviderData方法");
    return Stream<MyModel>.periodic(Duration(seconds: 1), getMyModel);
  }

  MyModel getMyModel(int count) {
    print("getMyModel方法");
    count++;
    if (count > 60) {
      return MyModel(counter: 60);
    }else {
      return MyModel(counter: count);
    }
  }

  @override
  Widget build(BuildContext context) {
    print("build方法来了");
    return StreamProvider(
        initialData: MyModel(counter: 0),
        create: getStreamProviderData, // 当这个函数执行的时候,会渲染UI
        child: Scaffold(
          appBar: AppBar(
            title: Text('FutureProvider'),
          ),
          body: Column(
            children: <Widget>[
              Builder(builder: (context) {
                MyModel _model = Provider.of<MyModel>(context);
                return Container(
                  margin: const EdgeInsets.only(top: 20),
                  width: MediaQuery.of(context).size.width,
                  padding: const EdgeInsets.all(20),
                  alignment: Alignment.center,
                  color: Colors.lightBlueAccent,
                  child: Text('当前是:${_model.counter}'),
                );
              }),
              Consumer<MyModel>(builder: (context, model, child) {
                return Container(
                  margin: const EdgeInsets.only(top: 20),
                  width: MediaQuery.of(context).size.width,
                  padding: const EdgeInsets.all(20),
                  alignment: Alignment.center,
                  color: Colors.lightGreen,
                  child: Text(
                    '${model.counter}',
                  ),
                );
              }),
              Consumer<MyModel>(builder: (context, model, child) {
                return FlatButton(
                    color: Colors.tealAccent,
                    onPressed: model.incrementCounter,
                    child: Icon(Icons.add));
              }),
            ],
          ),
        ));
  }
}

4、MultiProvider
描述:可以组合Provider所提供的类,给Ui提供多个数据Model。

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class MyHomePage5 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<BannerModel>(create: (context) => BannerModel()),
        ChangeNotifierProvider<ListModel>(create: (context) => ListModel()),
      ],
      child: Scaffold(
        appBar: AppBar(
          title: Text('provider'),
        ),
        body: Column(
          children: <Widget>[
            Builder(
              builder: (context) {
                BannerModel modol = Provider.of<BannerModel>(context);
                return Container(
                    margin: const EdgeInsets.only(top: 20),
                    width: MediaQuery.of(context).size.width,
                    padding: const EdgeInsets.all(20),
                    alignment: Alignment.center,
                    color: Colors.lightBlueAccent,
                    child: Text('当前Banner有几个:${modol.counter}'));
              },
            ),
            Consumer<ListModel>(
              builder: (context, model, child) {
                return Container(
                  margin: const EdgeInsets.only(top: 20),
                  width: MediaQuery.of(context).size.width,
                  padding: const EdgeInsets.all(20),
                  alignment: Alignment.center,
                  color: Colors.lightGreen,
                  child: Text(
                    '当前Banner有几个:${model.counter}',
                  ),
                );
              },
            ),
            Consumer<BannerModel>(
              builder: (context, model, child) {
                return FlatButton(
                    color: Colors.tealAccent,
                    onPressed: model.getBanner,
                    child: Text("获取banner"));
              },
            ),
            Consumer<ListModel>(
              builder: (context, model, child) {
                return FlatButton(
                    color: Colors.tealAccent,
                    onPressed: model.getList,
                    child: Text("获取列表"));
              },
            ),
          ],
        ),
      ),
    );
  }
}

class BannerModel with ChangeNotifier {
  int counter = 0;

  Future<void> getBanner() async {
    await Future.delayed(Duration(microseconds: 500));
    counter++;
    notifyListeners();
    print(counter);
  }
}

class ListModel with ChangeNotifier {
  int counter = 0;

  Future<void> getList() async {
    await Future.delayed(Duration(microseconds: 500));
    counter++;
    notifyListeners();
    print(counter);
  }
}

5、ProxyProvider
描述:当一个model依赖另一个model时,就以用ChangeNotifierProxyProvider把依赖的model推给被依赖model对像。当前例子模拟的是picmodel成功后,submitmodel才能成功。(场景:点击提交按钮的时候,先图片上传,成功了页面才提交成功)

import 'package:provider/provider.dart';
import 'package:flutter/material.dart';

class MyHomePage6 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<PicModel>(create: (context) => PicModel()),
        ProxyProvider<PicModel, SubmitModel>(
          update: (context, myModel, anotherModel) => SubmitModel(myModel),
        ),
      ],
      child: Scaffold(
        appBar: AppBar(
          title: Text('provider'),
        ),
        body: Column(
          children: <Widget>[
            Builder(
              builder: (context) {
                PicModel modol = Provider.of<PicModel>(context);
                return Container(
                    margin: const EdgeInsets.only(top: 20),
                    width: MediaQuery.of(context).size.width,
                    padding: const EdgeInsets.all(20),
                    alignment: Alignment.center,
                    color: Colors.lightBlueAccent,
                    child: Text('提交图片:${modol.counter}'));
              },
            ),
            Consumer<PicModel>(
              builder: (context, model, child) {
                return FlatButton(
                    color: Colors.tealAccent,
                    onPressed: model.upLoadPic,
                    child: Text("提交图片"));
              },
            ),
            Consumer<SubmitModel>(
              builder: (context, model, child) {
                return FlatButton(
                    color: Colors.tealAccent,
                    onPressed: () {
                      model.subMit().then((value) {
                          print("页面提交成功!");
                      });
                    },
                    child: Text("提交页面"));
              },
            ),
          ],
        ),
      ),
    );
  }
}

class PicModel with ChangeNotifier {
  int counter = 0;
  Future<void> upLoadPic() async {
//    counter++;
//    notifyListeners();
    await Future.delayed(Duration(seconds: 2));
    counter++;
    notifyListeners();
    print(counter);
    print("图片提交成功");
  }
}

class SubmitModel {
  PicModel _model;

  SubmitModel(this._model);

  Future<void> subMit() async {
    await _model.upLoadPic();
  }
}

点击下载demo
如果对您有用的话,点赞鼓励一下!

Flutter状态管理(使用Provider进行状态管理)

相关文章

网友评论

      本文标题:Flutter的状态管理-Provider简单使用

      本文链接:https://www.haomeiwen.com/subject/qhtmurtx.html