Flutter:集团,如何显示警报对话框

时间:2018-11-19 08:26:59

标签: view stream flutter alert

我是集团模式和流媒体方面的新手。我想在按下按钮时显示一个警报对话框,但找不到解决方法。其实我的代码是:

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();
      });
   }

但是,当然,它没有用。

6 个答案:

答案 0 :(得分:4)

构建工作时无法显示对话框。当您有新数据时,然后创建一个新的小部件。在这种情况下,可能不使用流可能会更好,但是如果需要,您应该使用

  

WidgetsBinding.instance.addPostFrameCallback((_)=> yourFunction(context));

在您的情况下

if (snapshot.hasData) { WidgetsBinding.instance.addPostFrameCallback((_) => showDialogFunction(context)); }

此代码将在构建方法后启动,因此将立即显示对话框。

Bloc函数始终返回小部件,因此,当流中有数据时,始终返回button()或不同的wiget

答案 1 :(得分:2)

这是我所做的,这可能是错误的,因为我还是新手。但是适用于我的情况。

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),
      ),
     );
 }

答案 2 :(得分:2)

您可以使用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(),
    );
  }
}

答案 3 :(得分:2)

我知道我参加聚会迟到了,但也许这会对某人有所帮助。 我目前正在学习 BLoC 并遇到了类似的问题。

首先,我想推荐flutter_bloc package from pub.dev。 它包含帮助您完成此操作的小部件,例如 BlocListenerBlocConsumer

如果您不想使用它,您可以尝试分别使用 StatefulWidgetlisten 并使用您的逻辑来显示对话框。 (还要确保您的流像我的示例一样广播,因此它可以有多个侦听器)

我制作了一个示例,您可以将其复制到 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);
    }));
  }
}

答案 4 :(得分:0)

此过程对我有用。 我在返回小部件之前给我的对话框打电话

Future.microtask(()=> showLoginSuccess(BuildContext context));

答案 5 :(得分:0)

我通过如下维护两个上下文解决了这个问题 **

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.这里我们称旧上下文实际上是在提供程序中注册的,2.context2 仅用于构建新的构建器小部件。 3.因此,我们可以通过导航传递 bloc 并在导航警报小部件中访问它,而无需创建它