Flutter: bloc,如何显示警告对话框
Flutter: bloc, how to show an alert dialog
我是 bloc pattern 和 stream 方面的新手。我想在按下按钮时显示一个警告对话框,但我找不到实现它的方法。其实我的代码是:
Widget button() {
return RaisedButton(
child: Text('Show alert'),
color: Colors.blue[700],
textColor: Colors.white,
onPressed: () {
bloc.submit();
});
}
return Scaffold(
appBar: AppBar(
title: Text("Title"),
),
body: StreamBuilder(
stream: bloc.getAlert,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text("I have Dataaaaaa ${snapshot.data}");
} else
return ListView(
children: <Widget>[
Container(
button()
)
...
BLoC:
final _submissionController = StreamController();
Stream get submissionStream=> _submissionController.stream;
Sink get submissionSink=> _submissionController.sink;
我尝试做类似的事情:
Widget button() {
return StreamBuilder(
stream: submissionStream
builder: (context, snapshot){
if (snapshot.hasData){
return showDialog(...)
}else
return RaisedButton(
child: Text('Show alert'),
color: Colors.blue[700],
textColor: Colors.white,
onPressed: () {
bloc.submit();
});
}
但是,当然,它没有用。
构建工作时无法显示对话框。当您有新数据时,您就可以创建一个新的小部件。在这种情况下不使用流可能对您更好,但如果有必要,您应该使用
WidgetsBinding.instance.addPostFrameCallback((_) => yourFunction(context));
或
Future.microtask(() => showDialogFunction(context));
如果
if (snapshot.hasData) {
WidgetsBinding.instance.addPostFrameCallback((_) => showDialogFunction(context));
}
此代码将在构建方法后启动,因此对话框会立即显示。
Bloc 函数总是 return 小部件,所以当流有数据时总是 return button() 或不同的小部件
这是我所做的,可能是错误的,因为我也是 flutter 的新手。但适用于我的场景。
Widget build(BuildContext context) {
final authBloc = BlocProvider.of<AuthBloc>(context);
authBloc.outServerResponse.listen((serverResponse) {
if (serverResponse.status == 'success') {
_navigateToLogin();
} else {
_showSnakBar(serverResponse.message);
}
});
.... Rest of the code which returns the widget,
which in my case is form widget with button for submitting as follows,
onPressed: () {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
authBloc.processRegister.add(_registrationData.toMap());
}
}
outServerResponse 是 API POST 调用完成后输出的流。
authBloc.processRegister 是将表单数据传递给我的 Auth API 服务提供商的输入接收器。
_nagivateToLogin & _showSnakBar 是简单的函数
_navigateToLogin() {
Navigator.of(context).pop();
}
_showSnakBar(String msg) {
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text(msg),
),
);
}
您可以使用 BlocListener 显示对话框、快捷栏或导航到新页面。
使用这种方法,您可能希望重构以依赖于 bloc 状态,而不是直接访问流。
return Scaffold(
appBar: AppBar(
title: Text("Title"),
),
body: BlocProvider<YourBloc>(
create: () => YourBloc(),
child: Stack([
SnackbarManager(),
YourScreen(),
]),
),
);
...
/// This is basically an empty UI widget that only
/// manages the snackbar
class SnackbarManager extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocListener<YourBloc, YourBlocState>(
listener: (context, state) {
if (state.hasMyData) {
Scaffold.of(context).showSnackBar(SnackBar(
content:
Text("I got data"),
));
}
},
child: Container(),
);
}
}
这个过程对我有用。
我在 return 小部件
之前调用了我的对话框
Future.microtask(() => showLoginSuccess(BuildContext 上下文));
我知道我迟到了,但也许这会对某人有所帮助。
我目前正在学习 BLoC,并且 运行 遇到了类似的问题。
首先,我要推荐flutter_bloc package from pub.dev。
它包含可帮助您解决此问题的小部件,例如 BlocListener
和 BlocConsumer
.
如果你不想使用它,你可以尝试单独使用 StatefulWidget
和 listen
并使用你的逻辑来显示对话框。 (还要确保你的流像我的例子一样在广播,所以它可以有多个听众)
我做了一个示例,您可以将其复制粘贴到 dartpad.dev/flutter:
import 'dart:async';
import 'package:flutter/material.dart';
final myStream = StreamController<bool>.broadcast();
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
initState() {
super.initState();
myStream.stream.listen((show){
if(show)
showDialog(
barrierDismissible: false,
context: context,
builder: (context) {
return AlertDialog(
title: Text('MyDialog'),
actions: [
TextButton(
child: Text('Close'),
onPressed: (){
myStream.sink.add(false);
}),
]
);
}
);
if(!show) {
Navigator.pop(context);
}
});
}
@override
Widget build(BuildContext context) {
return Center(child: ElevatedButton(
child: Text('Show Alert'),
onPressed: (){
myStream.sink.add(true);
}));
}
}
我通过如下维护两个上下文解决了这个问题
**
BlocProvider of type A ==>widget class B(showdialog(context:context,builder(context2){
Blocprvider.value(value:Blocprovider.of<A>.context)
child:BlocListener(
listner(context2,state)
{//
your works
//}
child:AlertDialog( some widgets
a button function ()=> context.read<A>().function or property name
//
1.here 我们调用旧上下文,实际上它已向提供者注册,2. context2 仅用于构建新的构建器小部件。
3.hence 我们通过导航获取 bloc 并在导航警报小部件中访问而无需创建它
我是 bloc pattern 和 stream 方面的新手。我想在按下按钮时显示一个警告对话框,但我找不到实现它的方法。其实我的代码是:
Widget button() {
return RaisedButton(
child: Text('Show alert'),
color: Colors.blue[700],
textColor: Colors.white,
onPressed: () {
bloc.submit();
});
}
return Scaffold(
appBar: AppBar(
title: Text("Title"),
),
body: StreamBuilder(
stream: bloc.getAlert,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text("I have Dataaaaaa ${snapshot.data}");
} else
return ListView(
children: <Widget>[
Container(
button()
)
...
BLoC:
final _submissionController = StreamController();
Stream get submissionStream=> _submissionController.stream;
Sink get submissionSink=> _submissionController.sink;
我尝试做类似的事情:
Widget button() {
return StreamBuilder(
stream: submissionStream
builder: (context, snapshot){
if (snapshot.hasData){
return showDialog(...)
}else
return RaisedButton(
child: Text('Show alert'),
color: Colors.blue[700],
textColor: Colors.white,
onPressed: () {
bloc.submit();
});
}
但是,当然,它没有用。
构建工作时无法显示对话框。当您有新数据时,您就可以创建一个新的小部件。在这种情况下不使用流可能对您更好,但如果有必要,您应该使用
WidgetsBinding.instance.addPostFrameCallback((_) => yourFunction(context));
或
Future.microtask(() => showDialogFunction(context));
如果
if (snapshot.hasData) {
WidgetsBinding.instance.addPostFrameCallback((_) => showDialogFunction(context));
}
此代码将在构建方法后启动,因此对话框会立即显示。
Bloc 函数总是 return 小部件,所以当流有数据时总是 return button() 或不同的小部件
这是我所做的,可能是错误的,因为我也是 flutter 的新手。但适用于我的场景。
Widget build(BuildContext context) {
final authBloc = BlocProvider.of<AuthBloc>(context);
authBloc.outServerResponse.listen((serverResponse) {
if (serverResponse.status == 'success') {
_navigateToLogin();
} else {
_showSnakBar(serverResponse.message);
}
});
.... Rest of the code which returns the widget,
which in my case is form widget with button for submitting as follows,
onPressed: () {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
authBloc.processRegister.add(_registrationData.toMap());
}
}
outServerResponse 是 API POST 调用完成后输出的流。
authBloc.processRegister 是将表单数据传递给我的 Auth API 服务提供商的输入接收器。
_nagivateToLogin & _showSnakBar 是简单的函数
_navigateToLogin() {
Navigator.of(context).pop();
}
_showSnakBar(String msg) {
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text(msg),
),
);
}
您可以使用 BlocListener 显示对话框、快捷栏或导航到新页面。
使用这种方法,您可能希望重构以依赖于 bloc 状态,而不是直接访问流。
return Scaffold(
appBar: AppBar(
title: Text("Title"),
),
body: BlocProvider<YourBloc>(
create: () => YourBloc(),
child: Stack([
SnackbarManager(),
YourScreen(),
]),
),
);
...
/// This is basically an empty UI widget that only
/// manages the snackbar
class SnackbarManager extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocListener<YourBloc, YourBlocState>(
listener: (context, state) {
if (state.hasMyData) {
Scaffold.of(context).showSnackBar(SnackBar(
content:
Text("I got data"),
));
}
},
child: Container(),
);
}
}
这个过程对我有用。 我在 return 小部件
之前调用了我的对话框Future.microtask(() => showLoginSuccess(BuildContext 上下文));
我知道我迟到了,但也许这会对某人有所帮助。 我目前正在学习 BLoC,并且 运行 遇到了类似的问题。
首先,我要推荐flutter_bloc package from pub.dev。
它包含可帮助您解决此问题的小部件,例如 BlocListener
和 BlocConsumer
.
如果你不想使用它,你可以尝试单独使用 StatefulWidget
和 listen
并使用你的逻辑来显示对话框。 (还要确保你的流像我的例子一样在广播,所以它可以有多个听众)
我做了一个示例,您可以将其复制粘贴到 dartpad.dev/flutter:
import 'dart:async';
import 'package:flutter/material.dart';
final myStream = StreamController<bool>.broadcast();
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
initState() {
super.initState();
myStream.stream.listen((show){
if(show)
showDialog(
barrierDismissible: false,
context: context,
builder: (context) {
return AlertDialog(
title: Text('MyDialog'),
actions: [
TextButton(
child: Text('Close'),
onPressed: (){
myStream.sink.add(false);
}),
]
);
}
);
if(!show) {
Navigator.pop(context);
}
});
}
@override
Widget build(BuildContext context) {
return Center(child: ElevatedButton(
child: Text('Show Alert'),
onPressed: (){
myStream.sink.add(true);
}));
}
}
我通过如下维护两个上下文解决了这个问题 **
BlocProvider of type A ==>widget class B(showdialog(context:context,builder(context2){
Blocprvider.value(value:Blocprovider.of<A>.context)
child:BlocListener(
listner(context2,state)
{//
your works
//}
child:AlertDialog( some widgets
a button function ()=> context.read<A>().function or property name
//
1.here 我们调用旧上下文,实际上它已向提供者注册,2. context2 仅用于构建新的构建器小部件。 3.hence 我们通过导航获取 bloc 并在导航警报小部件中访问而无需创建它