美文网首页
关于flutter中的状态管理(三)(Stream版Provid

关于flutter中的状态管理(三)(Stream版Provid

作者: 晨曦中的花豹 | 来源:发表于2022-04-02 16:49 被阅读0次

    上一篇有个想法就是以ChangeNotifier为主, InheritedWidget来管理ChangeNotifier的思路,最终夭折,这篇主要搞一下使用StreamController和InheritedWidget组合方式来实现状态管理,依然是InheritedWidget管理StreamController, StreamController来最终完成状态的管理.
    (原创想法,如有雷同纯属巧合)
    先思考我们要的是什么效果,我需要在全局套一个InheritedWidget来传递StreamController以及数据,而且是数据与StreamController是一一对应的,所以我们可以将数据与StreamController放到一起,而且为了我的数据扩展,我可以这样来定义

    class CountModel<T> extends StreamObject {
      int count = 0;
      add() {
        count++;
        update();
      }
    }
    
    class StreamObject {
      final StreamController? _streamController = StreamController();
      StreamSink? get sink => _streamController?.sink;
      Stream? get stream => _streamController?.stream;
      void update() {
        sink?.add("");
      }
    }
    

    将数据类型继承自基类,基类中管理StreamController
    当然这里我们在StreamBuilder中使用的是count本身,所以sink.add只是用来触发重构的,所以这里随便传什么都可以,前提是你不再使用snapshot,而是使用数据本身
    创建InheritedWidget

    class PutStreamController<T extends StreamObject> extends InheritedWidget {
    
      T model;
    
      PutStreamController(
          {required this.model, Key? key, required Widget child })
          : super(key: key, child: child);
    
      static T? of<T extends StreamObject>(BuildContext context, {bool listen = true}) {
        PutStreamController<T>? inheritedWidget;
        inheritedWidget = ((context.getElementForInheritedWidgetOfExactType<PutStreamController<T>>())
            ?.widget as PutStreamController<T>?);
    
        return inheritedWidget?.model;
      }
    
      @override
      bool updateShouldNotify(covariant PutStreamController oldWidget) {
        return false;
      }
    }
    

    这里只是使用到了InheritedWidget传递数据的能力,所以updateShouldNotify可以返回false,以及我只需要通过getElementForInheritedWidgetOfExactType查询到我的数据即可
    使用起来是这样的

    void main() {
      Get.put(TestGetController());
      runApp(
          PutStreamController(
            model: CountModel(),
            child: const MyApp(),
          )
      );
    }
    
    class HomePage extends StatelessWidget {
      const HomePage({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: StreamBuilder(
              stream: PutStreamController.of<CountModel>(context)?.stream,
              builder: (context, AsyncSnapshot snapshot) {
                return Text("${PutStreamController.of<CountModel>(context)?.count}");
              },
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () async {
              PutStreamController.of<CountModel>(context)?.add();
            },
            child: const Icon(Icons.add),
          ),
        );
      }
    }
    

    现在整体来看是可以了,但是我一点都不想把StreamController暴露出来,所以可以对StreamBuilder进行封装

    typedef AsyncModelBuilder<T> = Widget Function(BuildContext context, T model);
    
    class ModelBuilder<T extends StreamObject> extends StatelessWidget {
      ModelBuilder({required this.builder,Key? key}) : super(key: key);
      AsyncModelBuilder<T?> builder;
    
      @override
      Widget build(BuildContext context) {
        T? model = PutStreamController.of<T>(context);
        return StreamBuilder(
          stream: model?.stream,
          builder: (context, _) => builder(context,model),
        );
      }
    }
    

    这样调用就变得简单了

    ModelBuilder<CountModel>(
      builder: (context,model)=>Text("${model?.count}"),
    )
    

    而之前是这样的...

    StreamBuilder(
          stream: PutStreamController.of<CountModel>(context)?.stream,
          builder: (context, AsyncSnapshot snapshot) {
            return Text("${PutStreamController.of<CountModel>(context)?.count}");
          },
    ),
    

    到这里一个基于StreamController和InheritedWidget的状态管理就完成了
    最终的代码

    import 'dart:async';
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(PutStreamController(
        model: CountModel(),
        child: const MyApp(),
      ));
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({Key? key}) : super(key: key);
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: const HomePage(),
        );
      }
    }
    
    class HomePage extends StatelessWidget {
      const HomePage({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: ModelBuilder<CountModel>(
              builder: (context,model)=>Text("${model?.count}"),
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () async {
              PutStreamController.of<CountModel>(context)?.add();
            },
            child: const Icon(Icons.add),
          ),
        );
      }
    }
    
    class PutStreamController<T extends StreamObject> extends InheritedWidget {
      final T model;
    
      const PutStreamController({required this.model, Key? key, required Widget child})
          : super(key: key, child: child);
    
      static T? of<T extends StreamObject>(BuildContext context,
          {bool listen = true}) {
        PutStreamController<T>? inheritedWidget;
        inheritedWidget = ((context
                .getElementForInheritedWidgetOfExactType<PutStreamController<T>>())
            ?.widget as PutStreamController<T>?);
    
        return inheritedWidget?.model;
      }
    
      @override
      bool updateShouldNotify(covariant PutStreamController oldWidget) {
        return false;
      }
    }
    
    class CountModel extends StreamObject {
      int count = 0;
      add() {
        count++;
        update();
      }
    }
    
    class StreamObject {
    
      final StreamController? _streamController = StreamController();
    
      StreamSink? get sink => _streamController?.sink;
    
      Stream? get stream => _streamController?.stream;
    
      void update() {
        sink?.add("");
      }
    }
    
    typedef AsyncModelBuilder<T> = Widget Function(BuildContext context, T? model);
    
    class ModelBuilder<T extends StreamObject> extends StatelessWidget {
      const ModelBuilder({required this.builder,Key? key}) : super(key: key);
      final AsyncModelBuilder<T> builder;
    
      @override
      Widget build(BuildContext context) {
        T? model = PutStreamController.of<T>(context);
        return StreamBuilder(
          stream: model?.stream,
          builder: (context, _) => builder(context,model),
        );
      }
    }
    

    这里你只需要关注于你的CountModel就可以了
    Provider是基于ChangeNotifier和InheritedWidget, ChangeNotifier来刷新InheritedWidget从而实现对应数据的刷新,主角是InheritedWidget,而今天的Stream与InheritedWidget的组合却是,以Stream为主的,所以我称之为Stream版本Provider

    相关文章

      网友评论

          本文标题:关于flutter中的状态管理(三)(Stream版Provid

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