StreamBuilder是否不重新渲染内部的小部件?

时间:2019-04-02 09:03:40

标签: flutter

我创建了此代码,我想发生的事情是当我按下按钮时,我希望饼图以新值(应该是旧值,但食物值增加1)重新呈现。 我正在使用pie_chart:0.8.0包中的一个饼图。 存款不过是pojo(字符串类别和int存款) bloc.dart包含bloc的全局实例,该流的getter和类型为流的初始化 这是我的代码:

import 'package:flutter/material.dart';
import 'package:pie_chart/pie_chart.dart';
import 'bloc.dart';
import 'Deposit.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'bloc Chart',
      theme: ThemeData(
        primarySwatch: Colors.blueGrey,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  Map<String, double> datamap = new Map();

  @override
  Widget build(BuildContext context) {
    datamap.putIfAbsent("Food", () => 5);
    datamap.putIfAbsent("transportation", () => 3);
    return Scaffold(
      appBar: AppBar(
        title: Text("PieChart using blocs"),
      ),
      body: Column(
        children: <Widget>[
          StreamBuilder<Deposit>(
              stream: bloc.data, //A stream of Deposit data
              builder: (context, snapshot) {
                addDeposit(Deposit("Food", 1), datamap);
                debugPrint("Value of food in map is: ${datamap["Food"]}");
                return PieChart(dataMap: datamap);
              }),
          SizedBox.fromSize(
            size: Size(20, 10),
          ),
          RaisedButton(
            onPressed: () {
              bloc.add(Deposit("Food", 1)); //returns the stream.add
            },
            child: Icon(Icons.add),
          ),
        ],
      ),
    );
  }

  void addDeposit(Deposit dep, Map<String, double> map) {
    if (map.containsKey(dep.category)) {
      map.update(dep.category, (value) => value + dep.price);
    } else
      map.putIfAbsent(dep.category, () => dep.price);
  }
}

2 个答案:

答案 0 :(得分:0)

我认为您的问题是该流不会触发新事件。您无需关闭流即可进行重建。我看不到您的代码中触发流的新事件的任何地方。查看下面的代码,以查看使用StatelessWidget更新StreamBuilder的简单方法。

class CustomWidgetWithStream extends StatelessWidget {
  final CustomBlock block = CustomBlock();

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        StreamBuilder(
            stream: block.stream,
            builder: (context, stream) {
              return Text("${stream.data.toString()}");
            }),
        RaisedButton(
          onPressed: () {
            block.incrementNumber();
          },
          child: Text("Increment"),
        )
      ],
    );
  }
}

class CustomBlock {
  num counter = 10;
  final StreamController<num> _controller = StreamController();

  Stream<num> get stream => _controller.stream;

  CustomBlock() {
    _controller.onListen = () {
      _controller.add(counter); // triggered when the first subscriber is added
    };
  }

  void incrementNumber() {
    counter += 1;
    _controller.add(counter); // ADD NEW EVENT TO THE STREAM
  }

  dispose() {
    _controller.close();
  }
}

尽管这是一个有效的代码段,但我强烈建议将您的小部件从StatelessWidget更改为StatefulWidget,这有两个原因: *如果您“旁听”,如果某个窗口小部件自己更改了内容,则它不是StatelessWidget,无状态窗口小部件仅显示提供给它的数据。在您的情况下,小部件正在处理水龙头,然后决定下一步做什么以及如何自我更新。 *如果使用的是流,则在有状态的小部件中,可以安全地关闭流,如上面的代码所示,没有安全的方法来关闭流。如果您不关闭流,则可能会出现不良行为甚至崩溃。

答案 1 :(得分:0)

这是我的bloc文件

import 'package:rxdart/rxdart.dart';
import 'package:testing/Deposit.dart';

class Bloc{

  final _data = new BehaviorSubject<Deposit>();

  Stream<Deposit> get data => _data.stream;

  Function(Deposit) get add => _data.sink.add;

  void dispose(){
    _data.close();
  }

}

Bloc bloc = new Bloc();