按下素材按钮后如何调用Stream Builder?

时间:2019-11-17 01:22:31

标签: flutter bloc

上下文:我遇到一个问题,由于某些原因,当我单击该按钮时,Stream Builder内部的逻辑没有被调用。他进行api调用以验证用户身份,然后输入stream: userBloc.authenticationUserStream但不输入builder

我曾尝试过什么:试图查看UserBloc类上是否存在某种返回问题,但我认为一切正确。我还有一些不涉及单击按钮的小部件(我可以从构造函数中获取api),并且工作正常,因此我认为问题可能出在单击状态。

这是我在用户界面中的代码:

 class _LoginScreenState extends State<LoginScreen> {

         @override
      void initState() {
        super.initState();
        userBloc = UserBloc();
      }
    }

 final loginButton = Material(
      elevation: 5.0,
      borderRadius: BorderRadius.circular(30.0),
      color: Color(0xff01A0C7),
      child: MaterialButton(
        minWidth: MediaQuery.of(context).size.width,
        padding: EdgeInsets.fromLTRB(20, 15, 20, 15),
        onPressed: () {
          userBloc.authenticateUser(emailController.text.toString(),
              passwordController.text.toString());
          StreamBuilder<ApiResponse<LoginResponse>>( // does not enter here
              stream: userBloc.authenticationUserStream,
              builder: (context, snapshot) {
                if (snapshot.hasData) {
                  switch (snapshot.data.status) {
                    case Status.LOADING:
                      return Loading(
                        loadingMessage: snapshot.data.message,
                      );
                      break;
                    case Status.COMPLETED:
                      Navigator.push(
                        context,
                        MaterialPageRoute(builder: (context) => MovieScreen()),
                      );
                      break;
                    case Status.ERROR:
                      Scaffold.of(context).showSnackBar(SnackBar(
                        content: Text("Error"),
                      ));
                      break;
                  }
                }
                return Container();
              });
        },
        child: Text("Login", textAlign: TextAlign.center),
      ),
    );

这是我的UserBloc

代码
class UserBloc {
  UserRepository userRepository;
  StreamController streamController;

  StreamSink<ApiResponse<LoginResponse>> get authenticationUserSink =>
      streamController.sink;

  Stream<ApiResponse<LoginResponse>> get authenticationUserStream =>
      streamController.stream;

  UserBloc() {
    streamController = StreamController<ApiResponse<LoginResponse>>();
    userRepository = UserRepository();
  }

  authenticateUser(String email, String password) async {
    authenticationUserSink.add(ApiResponse.loading("Logging"));
    try {
      // success
      LoginResponse loginResponse =
          await userRepository.authenticateUser(email, password);
      authenticationUserSink.add(ApiResponse.completed(loginResponse));
    } catch (e) {
      // error
      authenticationUserSink.add(ApiResponse.error(e.toString()));
    }
  }

  dispose() {
    streamController?.close();
  }
}

有人可以在按一下按钮后帮助我理解如何称呼这类东西。如有必要,我可以共享我的user repository代码,在此先感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

您可以参考此https://medium.com/flutter-community/handling-network-calls-like-a-pro-in-flutter-31bd30c86be1

您需要将StreamBuilder<ApiResponse<LoginResponse>>移到不在onPressed()中的body / UI子对象中
演示代码段

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Movie Mania')),
      backgroundColor: Colors.black54,
      body: RefreshIndicator(
        onRefresh: () => _bloc.fetchMovieList(),
        child: StreamBuilder<ApiResponse<List<Movie>>>(
          stream: _bloc.movieListStream,
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              switch (snapshot.data.status) {
                case Status.LOADING:
                  return Loading(
                    loadingMessage: snapshot.data.message,
                  );
                  break;
                case Status.COMPLETED:
                  return MovieList(movieList: snapshot.data.data);
                  break;
                case Status.ERROR:
                  return Error(
                    errorMessage: snapshot.data.message,
                    onRetryPressed: () => _bloc.fetchMovieList(),
                  );
                  break;
              }
            }
            return Container();
          },
        ),
      ),
    );
  }