快照在Bloc中没有数据

时间:2020-03-29 11:38:45

标签: flutter flutter-layout bloc

我正在尝试通过创建动态简单主题管理器来学习Bloc。我创建了一个名为theme_bloc的类:

class DefaultApi {
  final String name;
  final ThemeData theme;

  DefaultApi(this.name, this.theme);
}

class ThemeBloc {
  DefaultApi _defualt;

  ThemeBloc() {}

  final _themeManager = StreamController<DefaultApi>.broadcast();

  Stream<DefaultApi> get themeManager => _themeManager.stream;
  Function(DefaultApi) get changeTheme => _themeManager.sink.add;

  DefaultApi initialTheme() {
    _defualt = DefaultApi("light", ThemeManager.instance.lightTheme);
    return _defualt;

  }

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

要注入bloc类,我会使用像这样的提供程序:

class ThemeProvider with ChangeNotifier{
 ThemeBloc _bloc;

ThemeProvider(){
  _bloc = ThemeBloc();
}
ThemeBloc get bloc => _bloc;
}

我在StringBuilder类中使用main来设置主题,如下所示:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider.value(
      value: ThemeProvider(),
      child: Consumer<ThemeProvider>(
        builder: (crx, provider, child) {
          return StreamBuilder(
              initialData: provider.bloc.initialTheme(),
              stream: provider.bloc.themeManager,
              builder: (context, AsyncSnapshot<DefaultApi>snapshot) {
                return snapshot.hasData? MaterialApp(
                  title: 'Flutter Demo',
                  theme: snapshot.data.theme,
                  home: HomePage(),
                ):Container();
              });
        },
      ),
    );
  }

HomePage页上,我切换了主题,以在浅色和深色主题之间进行更改。

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final bloc = Provider.of<ThemeProvider>(context).bloc;
    return Scaffold(
      appBar: AppBar(
        title: Text("Theme manager"),
      ),
      body: StreamBuilder<DefaultApi>(
          stream: bloc.themeManager,
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return Switch(
                value: true,
                onChanged: (bool value) {
                },
              );
            } else if (!snapshot.hasData) {
              return Text("loading");
            }
            return Text("!!!!");
          }),
    );
  }

但是在运行后,仅加载会显示在屏幕上。

enter image description here

有人知道我怎么了吗?

1 个答案:

答案 0 :(得分:1)

如果StreamBuilder中的HomePage小部件具有initialData,您的问题将得到解决。像这样:

...
body: StreamBuilder<DefaultApi>(
          initialData: bloc.initialTheme(), // <<< new line 
          stream: bloc.themeManager,
          builder: (context, snapshot) {
...

此输入不是required。但是我不知道为什么缺席会引起问题。

更深层的考虑:

1。使用ChangeNotifierProvider

按照documentation的建议,使用ChangeNotifierProvider代替ChangeNotifierProvider.value。显然是因为您正在创建一个新实例

...
    return ChangeNotifierProvider(
      create: (_) => ThemeProvider(),
      child: Consumer<ThemeProvider>(
...


2。防止无用的收听

基于this guide,如果您使用提供程序仅调用操作,则必须使用listen: false来防止无用的重建。