使用 BLoC 模式和 StatelessWidget 时如何调用 dispose

Aug*_*eaz 7 flutter

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

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

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

我相信我终于想出了如何使用“BloC”模式使我的示例工作,但是我在调​​用 dispose() 方法时遇到了问题,因为我只使用 StatelessWidgets。

我尝试将 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();
Run Code Online (Sandbox Code Playgroud)

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

如果我应该手动关闭它们,在我的例子中你什么时候调用 dispose() ?

har*_*rla 1

您可以使用 flutter 的提供程序包。它有用于处置的回调,您可以在其中处置您的块。提供者是继承的小部件,并提供了一种干净的方式来管理块。顺便说一句,我仅将无状态小部件与提供者和流一起使用。