Flutter 局部刷新(一)——StreamBuilder

169 阅读1分钟

参考juejin.cn/post/706336… 实现了一个跑马灯效果

Animation.gif

其中主程序为

import 'dart:async';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_test/stream_build_util.dart';

class TResponsive extends StatelessWidget {
  TResponsive({super.key});
  final sequenceList = [
    {
      'color': Colors.black,
    },
    {
      'color': Colors.black,
    },
    {
      'color': Colors.black,
    },
    {
      'color': Colors.black,
    },
    {
      'color': Colors.black,
    },
    {
      'color': Colors.black,
    },
    {
      'color': Colors.black,
    },
    {
      'color': Colors.black,
    },
    {
      'color': Colors.black,
    },
    {
      'color': Colors.black,
    },
  ];
  Timer? timer;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('跑马灯'),
      ),
      body: Container(
        child: Column(
          children: [
            Row(
              children: [
                ElevatedButton(
                    onPressed: () {
                      timer =
                          Timer.periodic(Duration(milliseconds: 20), (timer) {
                        int value = Random().nextInt(10);
                        if (sequenceList[value]['color'] == Colors.blue) {
                          sequenceList[value]['color'] = Colors.black;
                        } else {
                          sequenceList[value]['color'] = Colors.blue;
                        }
                        StreamBuildUtil.instance
                            .getStream('sequenceList')
                            .changeData(sequenceList);
                      });
                    },
                    child: Text('开始闪烁')),
                ElevatedButton(
                    onPressed: () {
                      timer!.cancel();
                      sequenceList.forEach((element) {
                        element['color'] = Colors.black;
                      });
                      StreamBuildUtil.instance
                          .getStream('sequenceList')
                          .changeData(sequenceList);
                    },
                    child: Text('复位')),
              ],
            ),
            StreamBuildUtil.instance.getStream('sequenceList').addObserver((t) {
              return Column(
                children: [
                  for (var item in t)
                    Container(
                      width: 20,
                      height: 20,
                      color: item['color'] as Color,
                      margin: EdgeInsets.only(bottom: 10),
                    )
                ],
              );
            }, initialData: sequenceList)
          ],
        ),
      ),
    );
  }
}



其中StreamBuildUtil 代码为

import 'dart:collection';

import 'stream_build.dart';

/// 局部刷新工具类
class StreamBuildUtil {
  static StreamBuildUtil? _instance;

  StreamBuildUtil._();

  factory StreamBuildUtil() {
    return instance;
  }

  static StreamBuildUtil get instance => _getInstance();

  static StreamBuildUtil _getInstance() {
    if (_instance == null) {
      _instance = StreamBuildUtil._();
    }
    return _instance ?? StreamBuildUtil._();
  }

  final HashMap<String, StreamBuild> dataBus = HashMap();

  /// key = 刷新局部标记
  StreamBuild getStream(String key) {
    if (!dataBus.containsKey(key)) {
      StreamBuild streamBuild = StreamBuild.instance(key);
      dataBus[key] = streamBuild;
    }
    if (dataBus[key] == null) {
      return StreamBuild.instance(key);
    } else {
      return dataBus[key]!;
    }
  }

  void onDisposeAll() {
    if (dataBus.length > 0) {
      dataBus.values.forEach((f) => f.dis());
      dataBus.clear();
    }
  }

  void onDisposeKey(String? key) {
    if (dataBus.length > 0) {
      dataBus.remove(key);
    }
  }
}


StreamBuild 代码为

import 'dart:async';

import 'package:flutter/material.dart';

import 'stream_build_util.dart';

/// 局部刷新状态
class StreamBuild<T> {
  late StreamController<T> _controller;

  T? t;

  final String key;

  StreamBuild(this.key) {
    _controller = StreamController.broadcast();
  }

  factory StreamBuild.instance(String key) {
    return StreamBuild<T>(key);
  }

  get outer => _controller.stream;

  get data => t;

  // 改变数据发送
  changeData(T t) {
    this.t = t;
    _controller.sink.add(t);
  }

  dis() {
    _controller.close();
  }

// 监听者
  Widget addObserver(Widget Function(T t) ob, {required T initialData}) {
    this.t = data ?? initialData;
    // var streamBuild = this as StreamBuild<T>;
    return StreamBuilderWidget<T>(
      streamBuild: this,
      builder: ob,
      initialData: initialData,
    );
  }
}

class StreamBuilderWidget<T> extends StatefulWidget {
  final StreamBuild<T> streamBuild;
  final Widget Function(T t) builder;
  final T? initialData;

  const StreamBuilderWidget(
      {Key? key,
      required this.streamBuild,
      required this.builder,
      required this.initialData})
      : super(key: key);

  @override
  _StreamBuilderWidgetState createState() => _StreamBuilderWidgetState<T>();
}

class _StreamBuilderWidgetState<T> extends State<StreamBuilderWidget> {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder<T>(
        initialData: widget.initialData,
        stream: widget.streamBuild.outer,
        builder: (context, n) {
          return widget.builder(n.data as T);
        });
  }

  @override
  void dispose() {
    super.dispose();
    widget.streamBuild.dis();

    StreamBuildUtil.instance.onDisposeKey(widget.streamBuild.key); // 清除map数据
  }
}