Flutter状态管理Provider(一)

       Google2019I/O大会上被谷歌推荐,原本谷歌的provide被弃用,与大部分状态管理一样使用了InheritedWidget。基于Provider3.0
第二篇Flutter状态管理Provider(二)

Provider()

两种方式Provider()和Provider.value(),使用基本差不多,区别在于Provider()提供dispose参数,可以在传递一个方法销毁的时候被调用,方便StatelessWidget释放资源,使用Provider写一个bloc


Flutter状态管理Provider(一)_第1张图片
1794647-cf4839d4dccb3bab_gaitubao_300x555.gif
import 'dart:async';

class CountBloc {
  final StreamController _countController = StreamController();
  int count = 0;
  Stream stream;

  CountBloc() {
    stream = _countController.stream.asBroadcastStream();
  }

  add() {
    _countController.add(++count);
  }

  //关闭
  dispose() {
    _countController?.close();
  }
}

界面代码

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

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State {
  @override
  Widget build(BuildContext context) {
    //如果状态管理放在顶层 MaterialApp 之上,它的作用域是全局,任何界面都可以获取;
    return Provider(
      builder: (context) => CountBloc(),
      //dispose:在widget销毁的时候调用,方便关闭stream,可以防止内存泄露
      //特别是在在StatelessWidget中使用非常好,因为StatelessWidget没有dispose方法
      dispose: (context, value) => value.dispose(),
      child: MaterialApp(
        title: "provider",
        home: HomePage(),
      ),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("HomePage")),
      body: StreamBuilder(
          stream: Provider.of(context).stream,
          initialData: 0,
          builder: (context, snapshot) {
            return Center(child: Text("${snapshot.data}"));
          }),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.push(
              context, MaterialPageRoute(builder: (context) => SecondPage()));
        },
        child: Icon(Icons.arrow_forward_ios),
      ),
    );
  }
}

class SecondPage extends StatefulWidget {
  @override
  _SecondPageState createState() => _SecondPageState();
}

class _SecondPageState extends State {
  @override
  Widget build(BuildContext context) {
    CountBloc bloc = Provider.of(context);
    return Scaffold(
      appBar: AppBar(title: Text("第二页")),
      body: StreamBuilder(
          stream: bloc.stream,
          initialData: bloc.count,
          builder: (context, snapshot) {
            return Center(child: Text("${snapshot.data}"));
          }),
      floatingActionButton: FloatingActionButton(
        onPressed: () => bloc.add(),
        child: Icon(Icons.add),
      ),
    );
  }
}
  1. 下面使用ValueListenableProvider,它只支持单一数据的监听,有两种方式,一种ValueListenableProvider.value(),另一种ValueListenableProvider(),两种方式几乎是相同的。
    先介绍下Consumer和Provider:
//此方法将从BuildContext关联的小部件树中查找,它将返回找到的最近的类型变量T
Provider.of( BuildContext context,
     {bool listen = true}//listen:默认true监听状态变化,false为不监听状态改变
)
//也可以使用Consumer组件获取,Consumer可用在没有context的地方,还可以优化性能
Consumer({
    @required this.builder,//这边写布局
    this.child,//可以控制刷新性能优化,当数据数据发生改变,不会重新build,
  })
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "provider",
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    ValueNotifier count = ValueNotifier(0);
    //在HomePage里面写状态,它的作用域只在HomePage中
    return Scaffold(
      appBar: AppBar(title: Text("home")),
      body: ValueListenableProvider.value(
        value: count,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            LeftView(), CenterView(), RightView()
          ],
        ),
      ),
      floatingActionButton:
          FloatingActionButton(onPressed: () => count.value += 1,child: Icon(Icons.add),),
    );
  }
}

class LeftView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("LeftView:build");
    return Consumer(
        child: MyText(),
        builder: (context, value, child) {
          return Container(
              width: 100,
              height: 100,
              color: Colors.blue,
              alignment: Alignment.center,
              child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [child, Text("$value")]));
        });
  }
}

class MyText extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("MyText:build");
    return Text("数量");
  }
}

class CenterView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("CenterView:build");
    return Container(
      width: 100,
      height: 100,
      color: Colors.pink,
      alignment: Alignment.center,
      child: Text(
        //listen: false 不监听状态改变
        "数量\n${Provider.of(context, listen: false)}",
        textAlign: TextAlign.center,
      ),
    );
  }
}

class RightView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("RightView:build");
    return Container(
      width: 100,
      height: 100,
      color: Colors.green,
      alignment: Alignment.center,
      child: Text(
        "数量\n${Provider.of(context)}",
        textAlign: TextAlign.center,
      ),
    );
  }
}
Flutter状态管理Provider(一)_第2张图片
1794647-31a67f0a79b6b742_gaitubao_300x801.gif

1、观察日志发现蓝色LeftView和MyText初始化后没有重新build。
2、红色CenterView初始化后也没有重新build
3、绿色RightView会随着状态改变会重新build
总结使用Consumer可以有效的优化性能,使用ValueListenableProvider时Provider.of()获取部件树中状态同时也可以监听状态改变从而刷新部件。

你可能感兴趣的:(Flutter状态管理Provider(一))