【问题标题】:Streambuilder render twice, the first time with initial data the second one with correct data, but the widget doesn't updateStreambuilder 渲染两次,第一次使用初始数据,第二次使用正确数据,但小部件不更新
【发布时间】:2020-10-20 05:21:59
【问题描述】:

您好,我是 Flutter 的新手,我在状态方面遇到了麻烦。我正在使用 Bloc 来处理状态,但是当我尝试在第一个视图中设置状态时,我无法在第二个视图中显示它。

在第二个视图中,streambuilder 首先显示初始值和连接等待,然后获取正确的数据并将状态更改为活动,但小部件不更新。

第一次查看

class LoginScreen extends StatefulWidget {
  LoginScreen({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _LoginScreenState createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {


  Widget _divider() {
    return Container(
      margin: EdgeInsets.symmetric(vertical: 10),
      child: Row(
        children: <Widget>[
          SizedBox(
            width: 30,
          ),
          Expanded(
            child: Padding(
              padding: EdgeInsets.symmetric(horizontal: 30),
              child: Divider(
                thickness: 1,
              ),
            ),
          ),
          SizedBox(
            width: 20,
          ),
        ],
      ),
    );
  }

  final _emailController = TextEditingController();
  final _passwordController =TextEditingController();

  _updateEmail (String text) => userBloc.updateUser(text);


  Widget _emailPasswordWidget() {
    return Column(
      children: <Widget>[
        EntryFields("Ingresa tu email", value:_emailController, onchanged: _updateEmail),
        EntryFields("Ingresa tu Password",value: _passwordController, isPassword: true),
      ],
    );
  }

  _goSignupScreen() async { return Navigator.pushNamed(context, Routes.signupRoute ); }
  _goHomeScreen() async { 
      _updateEmail(_emailController.text);
      return Navigator.pushNamed(context, Routes.homeRoute );
    }


  @override
  Widget build(BuildContext context) {
    final height = MediaQuery.of(context).size.height;
    return Scaffold(
        body: Container(
      height: height,
      child: Stack(
        children: <Widget>[
          Positioned(
              top: -height * .15,
              right: -MediaQuery.of(context).size.width * .4,
              child: BezierContainer()),
          Container(
            padding: EdgeInsets.symmetric(horizontal: 20),
            child: SingleChildScrollView(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  SizedBox(height: height* 0.2),
                  Center(child:  AppIconWidget(image: 'assets/images/logo.png', scale: 0.1)),
                  SizedBox(height: 50),
                  _emailPasswordWidget(),
                  SizedBox(height: 20),
                  SubmitButton(title: 'Iniciar Sesión', onPressed: _goHomeScreen ),
                  Container(
                    padding: EdgeInsets.symmetric(vertical: 10),
                    alignment: Alignment.centerRight,
                    child: Text('Olvidaste tu contraseña?',
                        style: TextStyle(
                            fontSize: 14, fontWeight: FontWeight.w500)),
                  ),
                  _divider(),
                  FacebookSignInButton(onPressed: (){}),
                  GoogleSignInButton(onPressed: () {}),
                  SizedBox(height: height * .055),
                  AccountLabel(label: 'No tienes cuenta?', btnText: 'Registrate', onPressed: _goSignupScreen ),
                ],
              ),
            ),
          ),
          // Positioned(top: 40, left: 0, child: BackBtn() ),
        ],
      ),
    ),);
  }
}

集团

class UserBloc {
  final _userRepository = UserRepository();
  final _userController = PublishSubject();;

  Observable get getUser => _userController.stream;
  

  updateUser(user) async {
      var currentUser = await _userRepository.updateCurrentUser(user);
    _userController.sink.add(currentUser);
    return null;
  }

  
   dispose() {
    _userController.close();
  }
}

final userBloc = UserBloc();

提供者

class UserProvider {

   Future updateCurrentUser(user) async{
     return currentUser = user;
   }
}

存储库

class UserRepository {
  final userProvider = UserProvider();

  Future updateCurrentUser(user) {
    return userProvider.updateCurrentUser(user);
    }
}

第二次查看

class HomeScreen extends StatelessWidget {
  
 @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(title: Text('title')),
      body: StreamBuilder(
        initialData: 'here!',
        stream: userBloc.getUser,
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          print('...');
          print('${snapshot.data}');
          print('${snapshot.connectionState}');
          print('...');
          if (snapshot.hasError) return Text('Error: ${snapshot.error}');
          switch (snapshot.connectionState) {
            case ConnectionState.none:
              return Text('Select lot');
            case ConnectionState.waiting:
              return Text('Awaiting bids...');
            case ConnectionState.active:
              return Text('\$${snapshot.data}');
            case ConnectionState.done:
              return Text('\$${snapshot.data} (closed)');
          }
          return null; // unreachable
        },
      ),
    );
  
}

谢谢!

【问题讨论】:

    标签: flutter state bloc


    【解决方案1】:

    我认为最好使用 snapshot.hasData,而不是为 connectionState 进行切换

    if (snapshot.hasData) {
       return Text('\$${snapshot.data}');
    } else {
       return Text('Loading;);
    }
    

    【讨论】:

    • 我做到了,但它只渲染初始数据(这里!),但是当我看到日志时,我看到状态正在更新 I/flutter (21519): ... I/扑动(21519):在这里! I/flutter (21519): ConnectionState.waiting I/flutter (21519): ... I/flutter (21519): ... I/flutter (21519): 12345 I/flutter (21519): ConnectionState.active I/颤动(21519):...
    猜你喜欢
    • 2020-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-20
    • 1970-01-01
    • 2022-11-30
    • 1970-01-01
    • 2020-02-14
    相关资源
    最近更新 更多