Flutter状态管理Provider,简单上手

3,829 阅读3分钟

学习Flutter一段时间了,偶然看到大家都说状态管理,多数人都是用redux,对于一个Android开发人员来说之前根本没接触过,于是开始了解redux,之后又了解闲鱼推出的fish_redux,然后又看到Vadaski发表的一系列关于Flutter状态管理的文章,包括Scoped Model, Redux, BLoC,RxDart,provide(想了解的可以移步),看的是眼花缭乱。对于Redux,能看懂是怎么写的,但真要到应用的层面,感觉还是有些吃力,更不知道怎样维护好它,一时间也不知道用什么什么适合自己。后来又接触到google推荐的Provider,于是学习了下。接下来就用Provider来实现一个计数的例子。

第一步,添加Provider依赖

provider: ^2.0.1+1

pub地址:pub.dev/packages/pr…

第二步,创建Model

import 'package:provider/provider.dart';
class Counter with ChangeNotifier {//1
  int _count;
  Counter(this._count);

  void add() {
    _count++;
    notifyListeners();//2
  }
  get count => _count;//3
}

简单的一个Counter对象,里面只有一个字段_count

  1. 这里需要混入ChangeNotifier
  2. 写一个增加的方法,然后需要调用notifyListeners();这个方法是通知用到Counter对象的widget刷新用的。
  3. get方法

第三步,使用ChangeNotifierProvider

通常main()方法是这么写

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

我们要监听改变就要在MyApp()外面套一层,这个是全局的,于是如下

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

main() {
  runApp(ChangeNotifierProvider<Counter>.value(//1
    notifier: Counter(1),//2
    child: MyApp(),
  ));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      title: "Provider",
      home: HomePage(),
    );
  }
}

  1. ChangeNotifierProvider调用value()方法,里面传出notifierchild
  2. notifier设置了默认的Counter(1)

当然Provider不止提供了ChangeNotifierProvider,还有Provider,ListenableProvider,ValueListenableProvider,StreamProvider, 具体可以看wiki. 如果想管理多个对象可以用MultiProvider,如下

MultiProvider(
  providers: [
    Provider<User>.value(value: user),
    Provider<Goods>.value(value: goods),
    .....
  ],
  child: someWidget,
)

第四步,使用Provider获取Counter的值

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

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text("Home"),
        actions: <Widget>[
          FlatButton(
            child: Text("下一页"),
            onPressed: () =>
                Navigator.push(context, MaterialPageRoute(builder: (context) {
                  return SecondPage();
                })),
          ),
        ],
      ),
      body: Center(
        child: Text("${Provider.of<Counter>(context).count}"),//1
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Provider.of<Counter>(context).add();//2
        },
        child: Icon(Icons.add),
      ),
    );
  }
}
  1. Provider.of<Counter>(context).count获取_count的值,Provider.of<T>(context)相当于Provider去查找它管理的Counter(1)
  2. Provider.of<Counter>(context).add();调用Counter()中的add()方法

同样第二个页面也这样写,如下

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text("SecondPage"),
      ),
      body: Center(
        child: Text("${Provider.of<Counter>(context).count}"),//1
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Provider.of<Counter>(context).add();//2
        },
        child: Icon(Icons.add),
      ),
    );
  }
}

这样,当每个页面都点击+号按钮时,_count便会+1,同时通知并更新到使用它的地方。

完整代码,copy后可直接运行

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

main() {
  runApp(ChangeNotifierProvider<Counter>.value(
    notifier: Counter(1),
    child: MyApp(),
  ));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      title: "Provider",
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text("Home"),
        actions: <Widget>[
          FlatButton(
            child: Text("下一页"),
            onPressed: () =>
                Navigator.push(context, MaterialPageRoute(builder: (context) {
                  return SecondPage();
                })),
          ),
        ],
      ),
      body: Center(
        child: Text("${Provider.of<Counter>(context).count}"),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Provider.of<Counter>(context).add();
        },
        child: Icon(Icons.add),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text(Provider.of<String>(context)),
      ),
      body: Center(
        child: Text("${Provider.of<Counter>(context).count}"),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Provider.of<Counter>(context).add();
        },
        child: Icon(Icons.add),
      ),
    );
  }
}

class Counter with ChangeNotifier {

  int _count;

  Counter(this._count);

  void add() {
    _count++;
    notifyListeners();
  }

  get count => _count;
}

总结

看了那么多状态管理的,个人感觉Provider还是属于简单易用的,并且是google推荐的。但感觉还需要成长,让大家认可。我这里只是一个简单的使用,有一些地方也没讲太清楚还请大家见谅,同时也希望和各位学习Flutter的同学互相交流进步。