Flutter的狀態(tài)管理-Provider簡單使用

Provider的幾種使用方式

1冰单、Provider
描述:是為恒定的數(shù)據(jù)提供的方法(類)。當(dāng)一個(gè)widget只是從這個(gè)model中取數(shù)據(jù)灸促,而不去監(jiān)聽數(shù)據(jù)的變化而去重繪界面.

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('當(dāng)前是:${_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
描述:當(dāng)model對(duì)像中有數(shù)據(jù)變化時(shí)涵卵,需要觸發(fā)widget中的元素重繪,實(shí)現(xiàn)數(shù)據(jù)驅(qū)動(dòng)荒叼,這時(shí)我們需要用到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多了個(gè)_dispose函數(shù)被廓,
      會(huì)在適當(dāng)?shù)臅r(shí)候自動(dòng)銷毀坏晦,一般情況下只用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('當(dāng)前是:${_model.counter}'));
              },
            ),
            Consumer<MyModel>(
              // 獲取到provider提供出來的值
              child: Container(
                // consumer 里的child的組件是不會(huì)被渲染的嫁乘,builder里的組件是會(huì)被重新渲染的
                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));
              },
            ),
          ],
        ),
      ),
    );
  }
}

// 初始化一個(gè)單獨(dú)的子部件套進(jìn)去昆婿,看能不能用provider.of(context)獲取model
class MyText extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("MyText子部件的build方法來了");
    MyModel _model =
        Provider.of<MyModel>(context); // 這里的也能正常拿到Provider中的model的,因?yàn)槭枪蚕淼摹?    return Container(
      child: Text('當(dāng)前是MyText里的:${_model.counter}'),
    );
  }
}

class MyText2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("MyText2子部件的build方法來了");
    MyModel models =
        Provider.of<MyModel>(context); // 這里的也能正常拿到Provider中的model的蜓斧,因?yàn)槭枪蚕淼摹?    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提供一份初始的數(shù)據(jù)Model,通過給StreamProvider設(shè)置了一個(gè)每隔1秒更新一次的stream挎春,ui上的計(jì)數(shù)值也是每隔一秒改變一次看疙。

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, // 當(dāng)這個(gè)函數(shù)執(zhí)行的時(shí)候,會(huì)渲染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('當(dāng)前是:${_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提供多個(gè)數(shù)據(jù)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('當(dāng)前Banner有幾個(gè):${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(
                    '當(dāng)前Banner有幾個(gè):${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
描述:當(dāng)一個(gè)model依賴另一個(gè)model時(shí)相味,就以用ChangeNotifierProxyProvider把依賴的model推給被依賴model對(duì)像拾积。當(dāng)前例子模擬的是picmodel成功后殉挽,submitmodel才能成功。(場(chǎng)景:點(diǎn)擊提交按鈕的時(shí)候拓巧,先圖片上傳斯碌,成功了頁面才提交成功)

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();
  }
}

點(diǎn)擊下載demo
如果對(duì)您有用的話肛度,點(diǎn)贊鼓勵(lì)一下傻唾!

Flutter狀態(tài)管理(使用Provider進(jìn)行狀態(tài)管理)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市承耿,隨后出現(xiàn)的幾起案子冠骄,更是在濱河造成了極大的恐慌,老刑警劉巖加袋,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凛辣,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡职烧,警方通過查閱死者的電腦和手機(jī)扁誓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門防泵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蝗敢,你說我怎么就攤上這事捷泞。” “怎么了寿谴?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵裁良,是天一觀的道長。 經(jīng)常有香客問我趴樱,道長充石,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任峻厚,我火速辦了婚禮响蕴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘惠桃。我一直安慰自己浦夷,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布辜王。 她就那樣靜靜地躺著劈狐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪呐馆。 梳的紋絲不亂的頭發(fā)上肥缔,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音汹来,去河邊找鬼续膳。 笑死,一個(gè)胖子當(dāng)著我的面吹牛收班,可吹牛的內(nèi)容都是我干的坟岔。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼摔桦,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼社付!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起邻耕,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤鸥咖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后兄世,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體啼辣,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年碘饼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了熙兔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片悲伶。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖住涉,靈堂內(nèi)的尸體忽然破棺而出麸锉,到底是詐尸還是另有隱情,我是刑警寧澤舆声,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布花沉,位于F島的核電站,受9級(jí)特大地震影響媳握,放射性物質(zhì)發(fā)生泄漏碱屁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一蛾找、第九天 我趴在偏房一處隱蔽的房頂上張望娩脾。 院中可真熱鬧,春花似錦打毛、人聲如沸柿赊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽碰声。三九已至,卻和暖如春熬甫,著一層夾襖步出監(jiān)牢的瞬間胰挑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來泰國打工椿肩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瞻颂,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓覆旱,卻偏偏與公主長得像蘸朋,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子扣唱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容