【问题标题】:data = null on snapshot in stream builder流生成器中的快照上的数据 = null
【发布时间】:2019-12-15 19:40:31
【问题描述】:

我第一次尝试使用流将我的视图模型连接到我的屏幕,但我很难完全掌握这个概念。

我的屏幕:

class LoginAndSignupScreen extends StatefulWidget {
  LoginAndSignupScreen({@required this.viewModel});

  final LoginAndSignupScreenViewModelType viewModel;

  @override
  State<StatefulWidget> createState() => new _LoginAndSignupScreenState();
}

class _LoginAndSignupScreenState extends State<LoginAndSignupScreen> {
  Widget showErrorMessage() {
    return StreamBuilder<String>(
      initialData: "",
      stream: widget.viewModel.errorText,
      builder: (context, snapshot) {
          return new Text(
            snapshot.data,
            style: TextStyle(
                fontSize: 13.0,
                color: Colors.red,
                height: 1.0,
                fontWeight: FontWeight.w300
            ),
          );
        }
    );
  }

我的视图模型:

abstract class LoginAndSignupScreenViewModelType {
  Stream<String> get errorText;

  void signIn(String email, String password);
  void signUp(String email, String password, String firstName, String lastName);
}

class LoginAndSignupScreenViewModel implements LoginAndSignupScreenViewModelType {
  LoginAndSignupScreenViewModel({@required this.authenticationService,
                                 @required this.cloudStoreService});

  final AuthenticationServiceType authenticationService;
  final CloudStoreServiceType cloudStoreService;

  final errorController = StreamController<String>.broadcast();

  @override
  Stream<String> get errorText => errorController.stream;

  @override
  void signIn(String email, String password) async {
    try {
      String userId = await authenticationService.signIn(email, password);
      User user = await cloudStoreService.fetchUserWithId(userId)
        .whenComplete(loginCallback);
      print('Signed in: ${user.firstName} ${user.lastName}');
    } catch (error) {
      errorController.add(error);
    }
  }

  @override 
  void signUp(String email, String password, String firstName, String lastName) async {
    try {
      String userId = await authenticationService.signUp(email, password);
      User user = new User(userId, firstName, lastName);
      await cloudStoreService.createUser(user)
        .then(showHomeScreenIfValidUser);
      print('Signed up user: ${user.id}');
    } catch (error) {
        errorController.add(error);
    }
  }
}

当我这样做并运行时,我收到一条错误消息,指出 snapshot.data = null 我理解。我的问题是,如果没有错误字符串,我希望没有小部件。

谁能帮忙?

【问题讨论】:

  • 我看不到你在哪里使用snapshot.data...
  • @Benjamin 抱歉,已更新_LoginAndSignupScreenState
  • 如果您不希望小部件出现,请使用Visibility 小部件,您可以将其设置为根据条件不显示小部件。在您的情况下,我假设数据是否为空。
  • 实际上 @Benjamin Visibity 对我不起作用,如果 snapshot.data 为 null 它仍然失败

标签: flutter dart


【解决方案1】:

为了回答您的问题,可以根据snapshot.data 的值返回不同的小部件:

stream: widget.viewModel.errorText,
builder: (context, snapshot) {
  if (snapshot.hasData) {
    return Text(
      snapshot.data,
      style: TextStyle(
          fontSize: 13.0,
          color: Colors.red,
          height: 1.0,
          fontWeight: FontWeight.w300
      ),
    );
  }

  // returns an invisible widget
  return SizedBox.shrink();

}

除此之外,您知道您可以有一个Stream 来生成数据和错误吗?我想知道为什么你使用回调而不是一个流来处理所有事情,snapshot.data 有数据,snapshot.error 有错误。

【讨论】:

  • 谢谢!我不知道它有错误知道,但我可能应该猜到了。不过,我不太理解您在如何使用一个流中实现的意思。
  • 除了errorText 流,您可以简单地使用更通用的Stream&lt;User&gt; 并产生数据(User)和错误。使用StreamController 这意味着调用add 获取数据并调用addError 添加异常。
  • 祝你好运!如果您需要灵感,Firebase Auth 会做类似的事情。也许这个视频可以帮助:fireship.io/lessons/advanced-flutter-firebase
猜你喜欢
  • 2021-02-07
  • 2020-08-05
  • 1970-01-01
  • 2021-12-29
  • 1970-01-01
  • 2023-03-08
  • 2022-08-24
  • 2023-03-29
  • 2020-02-12
相关资源
最近更新 更多