美文网首页Flutter_功能Flutter
Flutter状态管理Provider(一)

Flutter状态管理Provider(一)

作者: 简wen | 来源:发表于2019-06-17 11:50 被阅读0次

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

    Provider()

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


    1794647-cf4839d4dccb3bab_gaitubao_300x555.gif
    import 'dart:async';
    
    class CountBloc {
      final StreamController<int> _countController = StreamController();
      int count = 0;
      Stream<int> 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<MyApp> {
      @override
      Widget build(BuildContext context) {
        //如果状态管理放在顶层 MaterialApp 之上,它的作用域是全局,任何界面都可以获取;
        return Provider<CountBloc>(
          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<CountBloc>(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<SecondPage> {
      @override
      Widget build(BuildContext context) {
        CountBloc bloc = Provider.of<CountBloc>(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<T>( BuildContext context,
         {bool listen = true}//listen:默认true监听状态变化,false为不监听状态改变
    )
    //也可以使用Consumer组件获取,Consumer可用在没有context的地方,还可以优化性能
    Consumer<T>({
        @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<MyApp> {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: "provider",
          home: HomePage(),
        );
      }
    }
    
    class HomePage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        ValueNotifier<int> count = ValueNotifier(0);
        //在HomePage里面写状态,它的作用域只在HomePage中
        return Scaffold(
          appBar: AppBar(title: Text("home")),
          body: ValueListenableProvider.value(
            value: count,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                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<int>(
            child: MyText(),
            builder: (context, value, child) {
              return Container(
                  width: 100,
                  height: 100,
                  color: Colors.blue,
                  alignment: Alignment.center,
                  child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[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<int>(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<int>(context)}",
            textAlign: TextAlign.center,
          ),
        );
      }
    }
    
    1794647-31a67f0a79b6b742_gaitubao_300x801.gif

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

    相关文章

      网友评论

        本文标题:Flutter状态管理Provider(一)

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