我正在尝试通过创建动态简单主题管理器来学习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("!!!!");
}),
);
}
但是在运行后,仅加载会显示在屏幕上。
有人知道我怎么了吗?
答案 0 :(得分:1)
如果StreamBuilder
中的HomePage
小部件具有initialData
,您的问题将得到解决。像这样:
...
body: StreamBuilder<DefaultApi>(
initialData: bloc.initialTheme(), // <<< new line
stream: bloc.themeManager,
builder: (context, snapshot) {
...
此输入不是required
。但是我不知道为什么缺席会引起问题。
更深层的考虑:
按照documentation的建议,使用ChangeNotifierProvider
代替ChangeNotifierProvider.value
。显然是因为您正在创建一个新实例
...
return ChangeNotifierProvider(
create: (_) => ThemeProvider(),
child: Consumer<ThemeProvider>(
...
基于this guide,如果您使用提供程序仅调用操作,则必须使用listen: false
来防止无用的重建。