如何在按下 material 按钮后调用 Stream Builder?

How to call Stream Builder after pressing a material button?

Context:我遇到一个问题,由于某种原因,当我单击按钮时,没有调用 Stream Builder 中的逻辑。他调用 api 来验证用户身份并输入 stream: userBloc.authenticationUserStream 而不是 builder

我尝试了什么: 试图查看 UserBloc class 上是否存在某种 return 问题,但我认为一切都是正确的.我还有其他一些不涉及单击按钮的小部件(我可以从构造函数中调用 api)并且它工作正常,所以我认为问题可能出在单击状态上。

这是我来自 UI 的代码:

 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 代码,在此先感谢您的帮助。

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

您需要移出 StreamBuilder<ApiResponse<LoginResponse>> 到 body/UI child 而不是 onPressed()
演示代码片段

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