使用BLoC模式和StatelessWidget时如何调用处理

时间:2019-04-22 13:21:59

标签: flutter

我试图理解BLoC模式,但是我无法弄清楚在示例中何时何地调用dispose()。

我试图理解Flutter中的各种状态管理技术。

我想出了一个使用StatefulWidget,scoped_model和流构建的示例。

我相信我终于弄清楚了如何使用“ BloC”模式来使示例工作,但由于仅使用StatelessWidgets,因此在调用dispose()方法时遇到了问题。

我尝试将PageOne和PageTwo转换为StatefulWidget并调用dispose(),但最终在页面之间移动时过早关闭了流。

在我的示例中,是否有可能完全不用手动关闭流?

import 'package:flutter/material.dart';
import 'dart:async';

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder<ThemeData>(
      initialData: bloc.themeProvider.getThemeData,
      stream: bloc.streamThemeDataValue,
      builder: (BuildContext context, AsyncSnapshot<ThemeData> snapshot) {
        return MaterialApp(
          title: 'bloc pattern example',
          theme: snapshot.data,
          home: BlocPatternPageOne(),
        );
      },
    );
  }
}

// -- page_one.dart

class BlocPatternPageOne extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('(block pattern) page one'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            buildRaisedButton(context),
            buildSwitchStreamBuilder(),
          ],
        ),
      ),
    );
  }

  StreamBuilder<bool> buildSwitchStreamBuilder() {
    return StreamBuilder<bool>(
            initialData: bloc.switchProvider.getSwitchValue,
            stream: bloc.streamSwitchValue,
            builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
              return Switch(
                value: snapshot.data,
                onChanged: (value) {
                  bloc.sinkSwitchValue(value);
                },
              );
            },
          );
  }

  Widget buildRaisedButton(BuildContext context) {
    return RaisedButton(
            child: Text('go to page two'),
            onPressed: () {
              Navigator.of(context).push(
                MaterialPageRoute(
                  builder: (BuildContext context) {
                    return BlocPatternPageTwo();
                  },
                ),
              );
            },
          );
  }
}

// -- page_two.dart

class BlocPatternPageTwo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('(bloc pattern) page two'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            buildRaisedButton(context),
            buildSwitchStreamBuilder(),
          ],
        ),
      ),
    );
  }

  StreamBuilder<bool> buildSwitchStreamBuilder() {
    return StreamBuilder<bool>(
            initialData: bloc.switchProvider.getSwitchValue,
            stream: bloc.streamSwitchValue,
            builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
              return Switch(
                value: snapshot.data,
                onChanged: (value) {
                  bloc.sinkSwitchValue(value);
                },
              );
            },
          );
  }

  Widget buildRaisedButton(BuildContext context) {
    return RaisedButton(
            child: Text('go back to page one'),
            onPressed: () {
              Navigator.of(context).pop();
            },
          );
  }
}

// -- bloc.dart

class SwitchProvider {
  bool _switchValue = false;

  bool get getSwitchValue => _switchValue;

  void updateSwitchValue(bool value) {
    _switchValue = value;
  }
}

class ThemeProvider {
  ThemeData _themeData = ThemeData.light();

  ThemeData get getThemeData => _themeData;

  void updateThemeData(bool value) {
    if (value) {
      _themeData = ThemeData.dark();
    } else {
      _themeData = ThemeData.light();
    }
  }
}

class Bloc {
  final StreamController<bool> switchStreamController =
      StreamController.broadcast();
  final SwitchProvider switchProvider = SwitchProvider();

  final StreamController<ThemeData> themeDataStreamController =
      StreamController();
  final ThemeProvider themeProvider = ThemeProvider();

  Stream get streamSwitchValue => switchStreamController.stream;
  Stream get streamThemeDataValue => themeDataStreamController.stream;

  void sinkSwitchValue(bool value) {
    switchProvider.updateSwitchValue(value);
    themeProvider.updateThemeData(value);
    switchStreamController.sink.add(switchProvider.getSwitchValue);
    themeDataStreamController.sink.add(themeProvider.getThemeData);
  }

  void dispose() {
    switchStreamController.close();
    themeDataStreamController.close();
  }
}

final bloc = Bloc();

但是,目前一切正常,我想知道我是否应该担心手动关闭流或让Flutter自动处理它。

如果我应该手动关闭它们,那么在我的示例中何时调用dispose()?

1 个答案:

答案 0 :(得分:0)

您可以使用提供程序包进行振颤。它具有用于处置的回调,您可以在其中处置您的集团。提供程序是继承的窗口小部件,提供了一种干净的方法来管理块。顺便说一句,我仅将无状态窗口小部件与提供程序和流一起使用。